JS Execution Context?

KB LEE·2025년 2월 15일
0

JavaScript 펼쳐보기

목록 보기
2/5
post-thumbnail

1. 목적

JavaScript Execution Context가 무엇인지 이해하고, 내부 구조와 동작 방식을 한눈에 파악할 수 있도록 정리합니다.


2. JavaScript Execution Context란?

JavaScript 실행 컨텍스트(Execution Context)란, 자바스크립트 코드가 평가되고 실행되는 환경을 추상적으로 표현한 개념입니다.
쉽게 말해, 코드 실행에 필요한 모든 정보(변수, 함수 선언, 스코프, this 바인딩 등)를 담는 컨테이너라고 볼 수 있습니다.


3. Execution Context의 종류

  1. Global Execution Context

    • 자바스크립트 코드가 로드되면 단 한 번 생성되며, 애플리케이션이 종료될 때까지 유지되는 최상위 컨텍스트
    • 전역 스코프(Global Scope)에 선언된 변수, 함수 등이 포함됩니다.
  2. Function Execution Context

    • 함수를 호출할 때마다 생성
    • 함수 내부에서 사용하는 지역 변수, 매개변수(parameter), 내부 함수 선언 등이 포함됩니다.
  3. Eval Execution Context

    • eval() 함수를 호출할 때 생성되는 컨텍스트
    • 보안 및 성능 문제로 일반적으로 사용이 권장되지 않습니다.

4. 내부 구조

ES6 이후 스펙(ECMAScript 2015+)에서 Execution Context는 크게 아래 두 가지 환경(Environments)으로 구성됩니다.

  1. Lexical Environment
  2. Variable Environment

최근 ECMAScript 스펙(ES2024 등)에서도 여전히 같은 구조를 유지하고 있습니다.

4.1 Lexical Environment

  • let, const, class 선언처럼 블록 스코프를 가지는 선언들을 관리

  • 블록 스코프(Block Scope) 선언을 관리하는 환경 레코드(Environment Record)

    LexicalEnvironment = {
      EnvironmentRecord: { /* 현재 블록/함수의 식별자와 값 */ },
      outer: [null or 상위 LexicalEnvironment]
    }

(1) Environment Record

현재 스코프에 있는 변수, 함수, 상수 등이 어떤 값에 연결되어 있는지를 관리하는 맵(딕셔너리) 형태의 저장소를 의미합니다.
즉, 각 식별자(identifier)가 어떤 값과 바인딩되어 있는지를 기록하고 있습니다.

(2) Outer Environment Reference

  • 상위 스코프(외부 스코프)의 Lexical Environment를 참조하는 링크입니다.
  • 현재 스코프에서 변수를 찾지 못하면, outer를 따라 상위 Lexical Environment로 거슬러 올라가며 검색하는 구조(스코프 체인, Scope Chain)를 형성합니다.

4.2 Variable Environment

  • var 선언처럼 함수 스코프를 가지는 선언들을 관리
  • 함수 스코프(Function Scope) 선언을 관리하는 환경 레코드

즉, var와 달리 let/const는 블록 스코프를 형성하므로, 실행 시점에 별도의 Lexical Environment가 만들어지고 이를 통해 관리됩니다.

Q. Variable Environment와 Lexical Environment는 완전히 다른가요?
A. 내부적으로 동일한 EnvironmentRecord 구조를 공유하지만, 함수 스코프와 블록 스코프를 구분하기 위해 ‘논리적’으로 나누어 사용하는 개념입니다.
실제 구현에서는 같은 객체를 참조하다가, 블록({ })이 생성되면 새 Lexical Environment가 만들어져 let/const 선언을 관리하게 됩니다.


5. 코드 예시로 보는 Execution Context의 동작

아래 예시 코드를 통해 Execution Context가 생성되고 소멸되는 과정을 단계별로 살펴보겠습니다.

function outer(a) {
  var x = 10;
  let y = 20;
  {
    const z = 30;
    let y = 40;
  }

  function inner(b) {
    var x = 50;
    return x + b;
  }

  return inner(a);
}

outer(10);

5.1 Global Execution Context

  • 자바스크립트 엔진이 처음 코드를 로드할 때 전역 컨텍스트가 생성됩니다.
  • 전역에 선언된 outer 함수 등이 여기서 등록됩니다.

5.2 outer 함수 호출 → Outer Execution Context 생성

  1. 컨텍스트 생성(Context Creation)

    • 함수가 호출되면, 새로운 Function Execution Context가 만들어집니다.
    • 이때 함수의 매개변수와 var, let, const로 선언된 변수, 내부에 정의된 다른 함수 등이 먼저 등록됩니다.
    • letconst는 초기화되기 전에 TDZ(Temporal Dead Zone) 상태에 놓여 있습니다.
      ExecutionContext_outer = {
        EnvironmentRecord: {
          a: 10,        // 매개변수 초기화
          x: undefined, // var 선언(초기값 undefined)
          y: uninitialized, // let 선언(TDZ)
          inner: function inner(b) { ... } // 함수 선언
        },
        outer: GlobalExecutionContext.LexicalEnvironment
      }
  2. 컨텍스트 초기화(Context Initialization) & 실행(Execution)

    • 함수 내부 코드가 실행되면서 var, let, const로 선언된 변수들이 실제 값(또는 undefined)을 할당받고, TDZ가 해제됩니다.

      ExecutionContext_outer.EnvironmentRecord = {
        a: 10,
        x: 10,
        y: 20,
        inner: function inner(b) { ... }
      }
      
  3. 블록({ }) 실행

    • { } 블록이 시작되면, 새로운 Lexical Environment가 잠시 생성되어 블록 내 변수들을 관리합니다.

    • 블록이 끝나면 이 임시 Lexical Environment는 더 이상 참조되지 않아 GC(가비지 컬렉션)의 대상이 됩니다.

    • 블록 내부에 동일한 이름의 변수가 있다면 Shadowing이 발생하여, 블록 내부 변수와 외부 변수를 구분합니다.

       // 블록 진입 시
       BlockLexicalEnvironment = {
         EnvironmentRecord: {
           z: uninitialized,
           y: uninitialized // 블록 내부 y (외부 y와 shadowing)
         },
         outer: ExecutionContext_outer.LexicalEnvironment
       }
      
       // 블록 실행 후
       BlockLexicalEnvironment = {
         EnvironmentRecord: {
           z: 30,
           y: 40
         },
         outer: ... // 바깥 스코프 참조
       }
      
       // 블록 종료 시점에서
       // BlockLexicalEnvironment에 대한 참조는 사라짐
      

5.3 inner 함수 호출 → Inner Execution Context 생성

  • 함수 내부에 정의된 함수를 호출하면, 또 다른 Function Execution Context가 생성됩니다.

  • 매개변수와 내부 변수들이 등록되고, 실행 단계에서 실제 값이 할당됩니다.

  • 필요한 연산을 마치고 결과를 반환하면, 해당 컨텍스트는 소멸합니다.

    ExecutionContext_inner = {
      EnvironmentRecord: {
        b: 10,       // 매개변수 b에 10 할당
        x: undefined // var x 선언
      },
      outer: ExecutionContext_outer.LexicalEnvironment
    }
    

6. 후기

이 과정을 통해 결과만 확인하는 것이 아니라, 자바스크립트 내부에서 어떤 정보를 바탕으로 스코프와 변수를 처리하는지 이해할 수 있었습니다.

특히,

  • var vs let/const의 동작 차이와 TDZ(Temporal Dead Zone) 개념
  • Shadowing (상위 스코프와 동일한 이름의 변수를 다시 선언했을 때, 내부 스코프 변수가 우선)
  • 스코프 체인Outer Environment Reference
  • ES6 이후 변경된 this 바인딩 규칙

등을 종합적으로 살펴볼 수 있었습니다.

위 내용들은 추가적으로 포스팅하겠습니다 😎

내부 메커니즘을 이해하는 것이 단순 ‘코더’가 아닌 진정한 ‘개발자’로 나아가는 데 중요한 과정임을 느꼈습니다.

앞으로도 자바스크립트 엔진의 핵심 메커니즘을 비롯해, 최신 라이브러리·프레임워크 구조까지 단계적으로 살펴볼 예정입니다.
더 알차고 깔끔한 내용으로 찾아뵙겠습니다.

읽어주셔서 감사합니다!


7. 참고 자료

profile
한 발 더 나아가자

0개의 댓글