실행 컨텍스트와 클로저

이영민·2026년 1월 2일
post-thumbnail

1. 클로저(Closure)의 상세 정의 및 성질

클로저는 함수가 선언될 당시의 주변 환경인 렉시컬 스코프(Lexical Scope)를 기억하여, 함수가 해당 스코프 밖에서 호출되어도 그 환경에 저장된 변수에 접근할 수 있는 매커니즘을 의미한다.

  • 렉시컬 스코프의 결정: 자바스크립트의 엔진은 함수를 어디서 호출했는지가 아니라, 어디에 정의했는지에 따라 상위 스코프를 결정한다. 이를 렉시컬 스코핑이라 하며, 이 규칙이 클로저가 존재할 수 있는 근거가 된다.
  • 상태의 은닉화: 클로저를 통해 외부에서 직접 접근할 수 없는 사적인 변수(Private Variable)를 만들 수 있다. 이는 올바른 자금 관리를 위해 리스크 금액이나 매매 계약 수와 같은 핵심 데이터를 외부의 의도치 않은 수정으로부터 보호하는 데 유용하다.
  • 지속성: 일반적인 함수 내부 변수는 함수 종료 시 소멸하나, 클로저에 의해 참조되는 변수는 참조 카운트가 0이 될 때까지 메모리에 유지된다.

2. 실행 컨텍스트의 물리적 메모리 구조

실행 컨텍스트는 단순한 개념적 묶음이 아니라, 콜 스택과 힙 영역에 걸쳐 존재하는 물리적인 데이터 구조이다.

  • 콜 스택과 스택 프레임: 함수 호출 시 콜 스택에는 실행 컨텍스트의 '프레임(Frame)'이 생성된다. 여기에는 실행 흐름을 제어하기 위한 스택 포인터(SP), 복귀 주소, 그리고 힙 영역의 렉시컬 환경을 가리키는 포인터가 포함된다.
  • 힙(Heap) 영역의 렉시컬 환경(Lexical Environment): 실제 변수 값들이 저장되는 곳은 힙 영역이다. 렉시컬 환경은 객체 형태로 존재하며 다음과 같이 구성된다.
    • 환경 레코드(Environment Record): 현재 스코프에 선언된 식별자(변수, 함수 등)와 그 값을 저장한다.
    • 외부 환경 참조(Outer Environment Reference): 상위 스코프의 렉시컬 환경 객체를 가리키는 메모리 주소이다.
  • 구조적 분리의 이유: 콜 스택은 함수 종료 시 물리적으로 비워져야 하는 구조이다. 만약 변수 데이터가 스택에만 존재한다면 클로저가 불가능해지므로, 엔진은 데이터를 독립적인 힙 영역에 객체화하여 저장한다.

3. 클로저 발생 시 실행 컨텍스트의 변화 과정 (3단계)

1단계: 외부 함수 호출 및 내부 함수 정의

외부 함수(A)가 호출되면 콜 스택에 컨텍스트가 생성되고 힙에 A의 렉시컬 환경 객체가 생성된다. 이때 내부 함수(B)가 정의되면서, B 객체의 내부 슬롯인 [[Environment]]현재 실행 중인 A의 렉시컬 환경 주소값을 영구적으로 저장한다.

2단계: 외부 함수 종료 및 환경의 '잔존'

외부 함수 A의 실행이 종료되면 콜 스택의 프레임은 제거(Pop)된다. 하지만 A의 렉시컬 환경 객체는 사라지지 않는다. 반환된 내부 함수 B가 자신의 [[Environment]]를 통해 해당 객체를 참조하고 있기 때문이다. 가비지 컬렉터(GC)는 누군가 참조하고 있는 메모리 블록을 회수하지 않는 원칙에 따라 A의 환경을 힙 메모리에 보존한다.

3단계: 내부 함수 호출 및 스코프 체인 탐색

외부에서 보관 중이던 내부 함수 B를 호출하면 B의 실행 컨텍스트가 스택에 쌓인다. 이때 B의 컨텍스트 내부의 '외부 환경 참조(Outer Reference)'는 정의 시점에 저장해둔 A의 렉시컬 환경 주소를 그대로 복사해온다. B 내부의 코드가 실행될 때 특정 변수를 찾지 못하면, 이 참조 주소를 타고 힙 영역에 남아있는 A의 환경 레코드를 탐색한다.

0개의 댓글