코드를 실행하려면 환경이 필요하다
var x = 10이라는 코드를 실행하려면, 엔진은 몇 가지를 알아야 합니다:
x라는 변수를 어디에 저장할 것인가?- 이 코드의
this는 무엇 을 가리키는가? - 바깥 스코프에 있는 변수에 어떻게 접근할 것인가?
이 정보를 담고 있는 것이 실행 컨텍스트 (Execution Context) 입니다. JavaScript 엔진은 코드를 실행하기 전에 반드시 실행 컨텍스트를 먼저 생성합니다.
실행 컨텍스트의 종류
JavaScript에는 세 종류의 실행 컨텍스트가 있습니다:
- 전역 실행 컨텍스트 — 스크립트가 시작될 때 딱 하나 생성.
window(브라우저) 또는global(Node.js) 객체와 연결 - 함수 실행 컨텍스트 — 함수가 호출될 때마다 생성. 같은 함수를 10번 호출하면 10개의 컨텍스트가 생성됨
- eval 실행 컨텍스트 —
eval()호출 시 생성 (거의 쓰이지 않음)
실행 컨텍스트의 두 단계
각 실행 컨텍스트는 생성 단계 와 실행 단계 를 거칩니다.
생성 단계 (Creation Phase)
코드를 실행하기 전에 일어납니다:
this바인딩 결정- 변수/함수 선언을 찾아서 메모리에 등록
var변수 →undefined로 초기화- 함수 선언 → 함수 객체로 초기화 (전체가 메모리에 올라감)
let/const→ 등록되지만 초기화되지 않음 (TDZ)
- 외부 환경 참조 설정 (스코프 체인)
이것이 바로 호이스팅 의 실체입니다. 코드가 "끌어올려지는" 것이 아니라, 생성 단계에서 선언이 먼저 처리되는 것입니다.
실행 단계 (Execution Phase)
코드를 한 줄씩 실행합니다. 변수에 값을 할당하고, 함수를 호출하고, 표현식을 평가합니다.
콜스택과 실행 컨텍스트
함수가 호출되면 새 실행 컨텍스트가 콜스택에 push되고, 함수가 반환되면 pop됩니다. 아래 시각화에서 중첩 함수 호출 시 콜스택이 어떻게 변하는지 확인하세요.
핵심 관찰:
- 생성 단계 에서
var y가undefined로 초기화된 것을 볼 수 있습니다 — 이것이 호이스팅 - 함수 선언 (
bar) 은 생성 단계에서 바로 함수 객체로 초기화됩니다 bar()안에서x를 찾을 때, 자신의 컨텍스트 → foo → Global 순서로 스코프 체인 을 탐색합니다- 함수가 반환되면 컨텍스트가 pop 됩니다 — LIFO 순서
실행 컨텍스트의 내부 구조
ECMAScript 명세에 따르면 실행 컨텍스트는 이런 구성 요소를 가집니다:
LexicalEnvironment
let, const, 함수 선언이 저장되는 환경. 환경 레코드 (Environment Record) 와 외부 환경 참조 (Outer Reference) 로 구성됩니다.
VariableEnvironment
var 변수가 저장되는 환경. 함수/전역 수준에서는 LexicalEnvironment와 같은 객체를 가리킵니다. 하지만 let/const가 포함된 블록에 진입하면 LexicalEnvironment가 새 환경으로 교체되는 반면, VariableEnvironment는 그대로 유지됩니다 — 이것이 var가 블록을 무시하고 함수 스코프에 속하는 이유입니다.
ThisBinding
현재 컨텍스트의 this 값. 전역에서는 window, 메서드 호출에서는 호출 객체, new에서는 새 인스턴스를 가리킵니다. (5편에서 자세히 다룹니다)
호이스팅 다시 보기
실행 컨텍스트를 이해하면 호이스팅이 더 이상 마법이 아닙니다:
console.log(a); // undefined (var — 생성 단계에서 undefined로 초기화)
console.log(b); // ReferenceError (let — 생성 단계에서 등록만, 초기화 안 됨)
console.log(foo); // function (함수 선언 — 생성 단계에서 전체가 초기화)
var a = 1;
let b = 2;
function foo() {}var a— 생성 단계에서undefined로 초기화 → 접근 가능하지만 값은undefinedlet b— 생성 단계에서 등록만 → 초기화 전 접근 시 ReferenceError (TDZ)function foo— 생성 단계에서 함수 객체로 초기화 → 선언 전에도 호출 가능
정리
실행 컨텍스트는 JavaScript 실행의 기본 단위 입니다:
- 코드가 실행되려면 반드시 실행 컨텍스트가 필요하다
- 전역 컨텍스트는 하나, 함수 컨텍스트는 호출마다 생성
- 생성 단계에서 변수/함수를 등록하고 (→ 호이스팅), 실행 단계에서 코드를 수행
- 콜스택이 실행 컨텍스트의 생명주기를 관리
다음 단계
실행 컨텍스트가 "외부 환경 참조"를 통해 바깥 변수에 접근한다고 했습니다. 이 참조가 어떻게 연결되고, 변수를 찾을 때 어떤 순서로 탐색하는지 — 다음 글에서 스코프와 스코프 체인 을 자세히 살펴보겠습니다.