실행 컨텍스트(Execution Context)

2022-03-10 · 2 min read

요약

실행 컨텍스트란 소스코드를 실행하는 데 필요한 환경을 제공하고 코드의 실행 결과를 관리하는 영역입니다.

코드의 실행 순서는 실행 컨텍스트 스택에 의해, 스코프와 식별자는 실행 컨텍스트의 렉시컬 환경에 의해 관리됩니다.

소스코드의 평가와 실행

자바스크립트 엔진은 소스코드를 2개의 과정으로 나누어 처리합니다.

  • 소스코드의 평가
    • 함수와 변수의 선언문을 실행
    • 생성된 함수와 변수 식별자를 실행 컨텍스트가 관리하는 스코프에 등록
    • 평가 과정이 끝나야 소스코드가 실행됨
  • 소스코드의 실행
    • 선언문을 제외한 소스코드를 실행
    • 소스코드의 실행에 필요한 정보를 실행 컨텍스트가 관리하는 스코프에서 취득
    • 실행한 결과를 다시 스코프에 반영

코드가 실행되려면 스코프와 식별자의 관리와 코드 실행 순서의 관리가 필요한데, 스코프와 식별자는 렉시컬 환경으로, 코드의 실행 순서는 실행 컨텍스트 스택으로 관리하게 됩니다.

실행 컨텍스트 스택

코드를 통해 생성된 실행 컨텍스트는 스택으로 관리됩니다.

const a = 5;

function foo() {
  const b = 10;
  function bar() {
    console.log(a + b);
  }

  bar();
}

foo(); // 15

execution-context-stack

  1. 프로그램이 실행되고 전역 코드가 평가되면 전역 실행 컨텍스트가 생성되어 실행 컨텍스트 스택에 추가됩니다. 이때 a, foo의 선언문이 실행되어 전역 실행 컨텍스트에 등록됩니다. 이후 전역 코드가 실행되고 foo 함수를 호출합니다.
  2. foo 함수가 호출되면 전역 코드의 실행은 일시 중단되고 제어권이 foo 함수로 넘어갑니다. 그리고 foo 함수를 평가하여 실행 컨텍스트를 생성하고 스택에 추가합니다. foo 내의 변수 b와 함수 barfoo 함수의 실행 컨텍스트에 등록됩니다. 이후 foo 함수를 실행하고 bar 함수를 호출합니다.
  3. bar 함수가 호출되면 마찬가지로 제어권이 bar 함수로 넘어갑니다. bar 함수의 실행 컨텍스트가 생성되어 스택에 추가되고, 이후 함수를 실행합니다. console.log가 호출되면 우선 스코프 체이닝을 통해 console 식별자를 찾고, 이후 console 객체에서 프로토타입 체이닝을 통해 log 식별자를 찾아 호출합니다. 그리고 함수의 인수로 전달된 ab 역시 스코프 체이닝을 통해 검색합니다.
  4. bar의 실행이 끝나면 다시 제어권이 foo 함수로 넘어오고, 실행이 끝난 bar 함수는 실행 컨텍스트 스택에서 제거됩니다.
  5. 이후 foo의 실행이 끝나 실행 컨텍스트 스택에서 제거되고, 제어권은 전역 코드로 넘어옵니다. 곧이어 전역 코드의 실행이 마저 끝나면 전역 실행 컨텍스트도 스택에서 제거됩니다.

렉시컬 환경

렉시컬 환경(Lexical Environment)은 코드의 실행에 있어 식별자와 스코프를 관리하는 역할을 합니다. 렉시컬 환경은 두 개의 컴포넌트로 구성됩니다.

  • Environment Record: 스코프에 포함된 식별자를 등록하고 해당 식별자에 바인딩된 값을 관리하는 저장소입니다. 전역 코드냐 함수 코드냐에 따라 구성에 차이가 있습니다.
    • 전역 환경
      • Object Environment Record: BindingObject라는 전역 객체와 연결됩니다. 전역 코드 평가 중 var로 선언한 변수와 함수 선언문으로 정의된 함수는 이 BindingObject를 통해 전역 객체의 프로퍼티와 메서드가 됩니다. 이때 프로퍼티는 암묵적으로 undefined를 할당하고, 메서드는 생성된 함수 객체를 즉시 할당합니다. 이 때문에 호이스팅이 발생합니다.
      • Declarative Environment Record: let, const로 선언한 전역 변수를 등록하고 관리합니다. 따라서 이들은 전역 객체의 프로퍼티가 되지 않습니다. 또한 var 변수와 달리 값을 초기화하지 않으므로 런타임에 실행 흐름이 변수 선언에 도달하기 전까지 일시적 사각지대(TDZ)에 빠지게 됩니다.
      • this Binding: 전역 객체를 바인딩합니다.
    • 함수 환경
      • Function Environment Record: 매개변수 및 함수 내부에서 선언된 변수와 함수를 등록하고 관리합니다.
      • this Binding: 함수 호출 방식에 따라 this 바인딩이 결정됩니다.
  • Outer Lexical Environment Reference: 상위 스코프(해당 실행 컨텍스트를 생성한 소스코드를 포함하는 상위 코드의 렉시컬 환경)을 가리킵니다. 이를 통해 스코프 체인을 구현합니다.
    • 전역 환경: 전역 코드를 포함하는 소스코드는 없으므로 null이 할당됩니다.
    • 함수 환경: 현재 이 함수를 평가하는 실행 컨텍스트의 렉시컬 환경의 참조가 할당됩니다.

블록 레벨 스코프

letconst로 선언한 변수는 블록 레벨 스코프를 따릅니다. 때문에 블럭 내에서 let이나 const로 변수가 선언될 경우 새로운 렉시컬 환경을 생성하여 교체합니다. 블록 렉시컬 환경의 Outer Lexical Environment Reference는 블록에 진입하기 전의 렉시컬 환경을 가리키며, 블록의 실행이 끝나면 다시 기존의 렉시컬 환경으로 되돌립니다.

참고 자료

  • 이웅모, 『모던 자바스크립트 Deep Dive』
Copyright 2022-2024.hanse-kimAll right reserved.