코어 자바스크립트

코어 자바스크립트 - 실행 컨텍스트

윤해용 2025. 5. 28. 18:02

 

 

실행 컨텍스트(execution context) 는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다. 이를 콜 스택에 쌓아올렸다가, 가장 위에 있는 컨텍스트와 관련있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장한다. 전역 공간에서 자동으로 생성되는 전역 컨텍스트와 eval 및 함수 실행에 의한 컨텍스트 등이 있다.

 

debugger 후 개발자 도구

 

 

전역 컨텍스트는 자바스크립트 파일이 열리는 순간 전역 컨텍스트가 활성화 된다. 위 사진에서는 outer 함수를 호출하면 환경 정보를 수집하고 outer 실행 컨텍스트를 생성한 후 콜 스택에 담는다. 콜 스택 맨 위에 쌓이는 순간이 곧 현재 실행할 코드에 관여하게 되는 시점임을 알수 있다.

 

환경 정보가 담기는 실행 컨텍스트 객체는 활성화되는 시점에 VariableEnvironment, LexicalEnvironment, ThisBinding의 세 가지 정보를 수집한다. ThisBinding에는 this로 저장된 객체가 저장된다.

 

 

 

VariableEnviroment

 

실행 컨텍스트를 생성할 때는 VariableEnvironment에 정보를 먼저 담고, 이를 그대로 복사해서 LexicalEnvironment를 만들고, 이후에는 LexicalEnvironment를 주로 활용하게 된다. 

 

 

 

 

LexicalEnvironment

VariableEnvironment와 LexicalEnvironments의 내부는 environmentRecord와 outer-EnvironmentReference로 구성되어 있다.

 

 

 

environmentRecord

현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장된다. 매개변수 식별자, 선언한 함수가 있을 경우 그 함수 자체, 선언된 변수의 식별자 등이 식별자에 해당한다. 컨텍스트 내부 전체를 처음부터 끝까지 쭉 훓어나가며 순서대로 수집한다. 

 

변수를 수집하는 과정을 모두 마쳤더라도 코드들은 실행되기 전의 상태이다. 코드가 실행되기 전임에도 불구하고 자바스크립트 엔진은 이밎 해당 환경에 속한 코드의 변수명들을 모두 알고 있는 셈이 된다. 여기서 environmentRecord의 수집 과정을 추상화한 개념인 호이스팅이 등장한다.

 

function a () {
  console.log(b);	
  var b = 'bbb';	// 수집 대상 (변수 선언)
  console.log(b); 
  function b () { }  // 수집 대상 (함수 선언)
  console.log(b);	
}


// 호이스팅으로 변환한 코드
function a () {
  var b;	
  var b = function b () { }
	
  console.log(b); // b 함수
  b = 'bbb'
  console.log(b); // bbb
  console.log(b); // bbb
}
a()

 

위 예시를 보면 a 함수를 실행하는 순간 a 함수의 실행 컨텍스트가 생성된다. 이 때 변수명과 함수 선언의 정보를 위로 끌어올린다(수집). 변수는 선언부와 할당부를 나누어 선언부만 끌어올리는 반면 함수 선언은 함수 전체를 끌어올린다.

 

여기서 함수 선언문과 함수 표현식의 차이가 발생하게 되는데 함수 선언문은 전체를 호이스팅하고 함수 표현식은 변수 선언부만 호이스팅한다.

 

 

 

outer-EnvironmentReference, 스코프, 스코프 체인

스코프는 식별자에 대한 유효범위이다. ES6에서는 함수 스코프, 블록 스코프라는 용어를 사용한다. 이러한 식별자의 유효범위를 안에서부터 바깥으로 차례로 검색해나가는 것을 스코프 체인이라고 한다. 그리고 이를 가능케 하는 것이 바로 LexicalEnvironments의 두 번째 수집 자료인 outer-EnvironmentReference이다.

 

outer-EnvironmentReference는 해당 함수가 선언된 위치의 LexicalEnvironments을 참조한다. 다음 코드 흐름을 보면서 구체적으로 알아보자.

 

var a = 1;
var outer = function () {
    var inner = function () {
        console.log(a);
        var a = 3;
    }
    inner();
    console.log(a);
}
outer();
console.log(a);

 

1. 시작 :  전역 컨텍스트가 활성화 된다. 전역 컨텍스트의 environmentRecord에 { a, outer } 식별자를 저장한다. 전역 컨텍스트는 선언 시점이 없으므로 outer-EnvironmentReference에는 아무것도 담기지 않는다.

 

2. 10번째 줄 : outer 함수를 호출한다. 전역 컨텍스트의 코드는 10번째 줄에서 임시중단되고, outer 실행 컨텍스트가 활성화되어 2번째 줄로 이동한다.

 

3. 2번째 줄 : outer 실행 컨텍스트의 environmentRecord에 { inner } 식별자를 저장한다. outer-EnvironmentReference에는 outer 함수는 전역 공간에서 선언되었으므로 전역 컨텍스트의 LexicalEnvironments를 참조 복사한다. [ GLOBAL, { a, outer } ] 라고 표기한다. 첫 번째(GLOBAL)은 실행 컨텍스트의 이름, 두 번째( { a, router } )는 environmentRecord 객체이다.

 

4. 7번째 줄 : inner 함수를 호출한다. outer 실행 컨텍스트의 코드는 7번째 줄에서 임시중단되고, inner 실행 컨텍스트가 활성화되어 3번째 줄로 이동한다.

 

5. 3번째 줄 : inner 실행 컨텍스트의 environmentRecord에 { a } 식별자를 저장한다. outer-EnvironmentReference는 [ outer, { inner } ]를 참조 복사한다. 

 

6. 4번째 줄 : 식별자 a 에 접근한다. 현재 활성화 상태인 inner의 컨텍스트의 environmentRecord에서 a를 검색한다. a가 발견되었지만 여기에는 아직 할당된 값이 없다.

 

 

7. 6번째 줄 : inner 함수 실행이 종료 된다. inner 실행 컨텍스트가 콜 스택에서 제거되고, 바로 아래의 outer 실행 컨텍스트가 다시 활성화 된다. 앞서 중단했던 7번째 줄 다음으로 이동한다.

 

 

8. 8번째 줄 : 식별자 a 에 접근한다. 이 때 자바스크립트 엔진은 활성화 된 outer 실행 컨텍스트의 LexicalEnvironments에 접근한다. 첫 요소인 environmentRecord에는 inner밖에 없다. outer-EnvironmentReference에 있는 environmentRecord로 넘어가는 식으로 계속 검색하면서 a가 있는지 찾아본다. 예시에서는 전역 LexicalEnvironments에 a가 있으므로 그 a에 저장된 값 1을 반환한다.

 

 

9. 9번째 줄 : outer 함수 실행이 종료되면서 outer 실행 컨텍스트가 콜 스택에서 제거된다. 전역 컨텍스트가 다시 활성화 된다.

 

 

10. 11번째 줄 : 식별자 a에 접근한다. 현재 활성화 된 전역 컨텍스트의 environmentRecord에서 a를 검색한다. 1을 출력하면서 전역 컨텍스트가 콜 스택에서 제거되고 종료된다.

 

 

스코프 체인 상에 있는 변수라고 해서 무조건 접근 가능하지 않다. 위 예시에서도 inner 함수의 a 에 접근하려고 하면 무조건 inner 스코프의 LexicalEnvironments부터 검색할 수 밖에 없다. inner 함수 내부에서 a 변수를 선언했기 때문에 전역에서 선언한 동일한 이름의 a 변수에는 접근할 수 없다. 이를 변수 은닉화(variable shadowing)라고 한다.

 

 

전역 컨텍스트의 LexicalEnvironments에 담긴 변수를 전역변수라 하고, 그 밖의 함수에 의해 생성된 실행 컨텍스트의 변수들은 모두 지역변수이다. 안전한 코드 구성을 위해 가급적 전역변수의 사용은 최소화 하는 것이 좋다.

 

 

 

 

 

코어 자바스크립트를 읽고 정리한 글입니다.

 

https://product.kyobobook.co.kr/detail/S000001766397

 

코어 자바스크립트 | 정재남 - 교보문고

코어 자바스크립트 | 자바스크립트의 근간을 이루는 핵심 이론들을 정확하게 이해하는 것을 목표로 합니다!최근 웹 개발 진영은 빠르게 발전하고 있으며, 그 중심에는 자바스크립트가 있다고

product.kyobobook.co.kr