Giyoun's Blog

실행 컨텍스트

2023-03-03

실행 컨텍스트

자바스크립트는 어떻게 실행되는가

소스코드 타입

  1. 전역 코드
  • 전역에 존재하는 소스 코드, 전역에 정의된 함수, 클래스 등의 내부 코드는 포함되지 않는다.
  1. 함수 코드
  • 함수 내부에 존재하는 소스코드, 함수 내부에 중첩된 함수, 클래스 등의 내부 코드는 포함되지 않는다.
  1. eval 코드
  • 빌트인 전역 함수인 eval 함수에 인수로 전달되어 실행되는 소스코드
  1. 모듈 코드
  • 모듈 내부에 존재하는 소스코드, 모듈 내부의 함수, 클래스 등의 내부코드는 포함되지 않는다.

소스코드의 평가와 실행

  • 자바스크립트 엔진은 소스코드 평가와 소스코드의 실행 두 가지 과정으로 나누어 처리한다.

소스코드 평가

  • 실행 컨텍스트를 생성하고 변수, 함수 등의 선언문만 먼저 실행하여 생성된 변수나 함수 식별자를 키로 실행 컨텍스트가 관리하는 스코프(렉시컬 환경의 환경레코드)에 등록한다.

소스코드의 실행

  • 평가가 끝나면 코드가 실행된다. (런타임)

실행 컨텍스트

소스코드를 실행하는데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역( 스코프 = 식별자 등록&관리 / 코드 실행순서 관리 / 모든 코드는 실행 컨텍스트를 통해 실행 및 관리)

  1. 전역 코드 평가
  2. 전역 코드 실행
  3. 함수 코드 평가
  4. 함수 코드 실행
// 전역변수 선언 const x = 1; const y = 2; // 함수 정의 function foo (a) { // 지역변수 선언 const x = 10; const y = 20; // 메서드 호출 console.log(a + x + y); // 130 } // 함수 호출 foo(100); // 메서드 호출 console.log(x + y); // 3
  • 코드가 실행되려면 스코프, 식별자, 코드 실행순서 등의 관리가 필요하다.
    • 선언에 의해 생성된 모든 식별자(변수, 함수, 클래스 등)를 스코프를 구분하여 등록하고 상태변화 (식별자에 바인딩된 값의 변화)를 지속적으로 관리할 수 있어야 한다.
    • 스코프는 중첩 관계에 의해 스코프 체인을 형성해야 한다. 즉, 스코프 체인을 통해 상위 스코프로 이동하며 식별자를 검색할 수 있어야 한다.
    • 현재 실행 중인 코드의 실행 순서를 변경(함수 호출에 의한 실행 순서 변경)할 수 있어야 하며 다시 되돌아갈 수 있어야 한다.

스택

  • 스코프와 식별자는 렉시컬 환경으로 관리하고 스택으로 순서를 관리한다.
  • 실행 컨텍스트 스택의 최상 위에 존재하는 실행 컨텍스트는 언제나 현재 실행 중인 코드의 실행 컨텍스트이다.
const x = 1; function foo () { const y = 2; function bar () { const z = 3; console.log(x + y + z); } bar(); } foo(); // 6
  1. 전역 코드의 평가와 실행 ( 전역변수 x, 함수 foo() )
  2. foo 함수 코드의 평가와 실행 ( 전역 코드 실행 일시 중단, foo 내부 코드)
  3. bar 함수 코드(중첩 함수)의 평가와 실행 (foo 함수 코드 실행 일시 중단, bar 내부 코드)
  4. foo 함수 코드로 복귀
  5. 전역 코드로 복귀

image

렉시컬 환경

  • 식별자와 실별자에 바인딩된 값, 그리고 상위 스코프에 대한 참조를 기록하는 자료구조 (실행 컨텍스트 구성 컴포넌트)
  • 실행 컨텍스트 스택 (코드 실행 순서 관리) ↔ 렉시컬 환경 (스코프와 식별자 관리)
  • 키와 값을 갖는 (객체 형태)스코프를 생성하여 식별자를 키로 등록하고 식별자에 바인딩 된 값을 관리

구성

  1. 환경 레코드
  • 스코프에 포함된 식별자 등록, 등록된 식별자에 바인딩 된 값 관리 저장소
  1. 외부 렉시컬 환경 참조
  • 상위 스코프를 참조 (해당 실행 컨텍스트를 생성한 소스코드를 포함하는 상위 코드의 렉시컬 환경) / 스코프 체인 형성 (단방향 링크드 리스트)

실행 컨텍스트 생성과 식별자 검색 과정

  1. 전역 객체 생성
  2. 전역 코드 평가
  3. 전역 코드 실행
  4. foo 함수 코드 평가
  5. foo 함수 코드 실행
  6. bar 함수 코드 평가
  7. bar 함수 코드 실행
  8. bar 함수 코드 종료
  9. foo 함수 코드 종료
  10. 전역 코드 실행 종료
var x = 1; const y = 2; function foo (a) { var x = 3; const y = 4; function bar (b) { const z = 5; console.log(a + b + x + y + z); } bar (10); } foo(20); // 42

image

  • 비어있는 전역 실행 컨텍스트를 생성하고 스택에 푸쉬
  • 전역 렉시컬 환경 생성, 전역 실행 컨텍스트에 바인딩
  • 전역 환경 레코드 → 객체 환경 레코드, 선언적 환경 레코드 / this 바인딩
  • 외부 렉시컬 환경 참조 결정

💡 함수를 어디서 호출했는지가 아니라 어디서 정의했는지에 따라 상위 스코프를 결정!


식별자 결정

  • 동일한 이름의 식별자가 다른 스코프에 존재 할 수도 있다. 어느 스코프의 식별자를 참조하면 되는지 결정해야 한다.
  • 식별자 결정을 위한 탐색은 실행 중인 실행 컨텍스트에서 시작한다.

image

console.log

  1. console 식별자 검색
  • 외부 참조 → 전역 참조 → 전역 객체 환경 레코드(binding object)
  1. log 메서드 검색
  • console 식별자에 바인딩 된 객체 (console 객체에서 log 메서드 검색)
댓글을 불러오는 중입니다.
CSR vs SSR

CSR? SSR? 뭐가 더 좋을까

클로저

클로저 제대로 알아보기

You can look back but don't regret it | All Right Reserved by Giyoun