실행 컨텍스트

자바스크립트의 실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아 놓은 객체이다. 실행 컨텍스트는 추상적 개념이기 때문에 설명하기 어렵지만 자바스크립트 코드의 실행과정을 살펴보며 느껴보자.

소스코드의 평가와 실행

모든 소스코드는 실행에 앞서 평가 과정을 거치며 실행하기 위한 준비를 한다.
자바스크립트 엔진은 소스코드를 평가실행의 과정으로 나누어 처리한다.

  1. 소스코드 평가
  1. 소스코드 실행

예를 들어, 다음과 같은 소스코드가 실행된다고 해보자.

var a;
var b = 2;
var a = 1;
  1. 소스코드 평가

    • 변수 선언문 var a;이 먼저 실행되고, var b = 2;에서 2로 할당은 이뤄지지 않고 식별자 b만 먼저 실행 컨텍스트가 관리하는 스코프에 등록된다. 등록과 동시에 undefined로 초기화 된다.
      Pasted image 20231015225728.png
  2. 소스코드 실행

    • 평가 과정이 끝나면 소스코드 실행 과정이 시작된다. 변수 선언문은 평가 과정에서 이미 실행됐고, 위의 코드에서는 할당문만 실행된다. 할당 결과를 실행 컨텍스트에 등록하여 관리한다.
      Pasted image 20231015230027.png

실행 컨텍스트의 역할

그럼 이제 다음 코드를 자바스크립트 엔진이 어떻게 평가하고 실행하는지 생각해보자.

var a = 1;
function outer() {
	function inner() {
		console.log(a); 
		var a = 3;
	}
	inner(); 
	console.log(a);
}
outer(); 
console.log(a);
  1. 전역 코드 평가

    • 전역 코드의 변수 선언문과 함수 선언문이 실행되고, 실행 컨텍스트가 관리하는 전역 스코프에 등록된다.
  2. 전역 코드 실행

    • 전역 코드 평가가 끝나면 런타임이 시작되어 전역 코드가 순차적으로 실행된다. 전역 변수에 값이 할당되고, 함수가 호출된다. 함수가 호출되면 전역 코드의 실행을 일시 중단하고 코드 실행 순서를 변경하여 함수 내부로 진입한다.
  3. 지역 함수 코드 평가

    • 지역 함수 내부의 매개변수와 지역 변수 선언문이 실행되고, 실행 컨텍스트가 관리하는 지역 스코프에 등록된다.
  4. 지역 함수 코드 실행

    • console.log 메서드를 호출하기 위해 식별자 console스코프 체인을 통해 검색한다. 이를 위해 지역 스코프는 상위 스코프인 전역 스코프와 연결되어야 한다.

이처럼 코드가 실행되려면 다음과 같이 스코프, 식별자, 코드 실행 순서 등의 관리가 필요하다.

  1. 선언에 의해 생성된 모든 식별자를 스코프를 구분하여 등록하고 상태 변화를 지속적으로 관리할 수 있어야 한다.
  2. 스코프는 중첩 관계에 의해 스코프 체인을 형성해야 한다. 즉, 스코프 체인을 통해 상위 스코프로 이동하며 식별자를 검색할 수 있어야 한다.
  3. 현재 실행 중인 코드의 실행 순서를 변경할 수 있어야 하며 되돌아갈 수도 있어야 한다.

이 모든 것을 관리하는 것이 바로 실행 컨텍스트다. 실행 컨텍스트는 소스코드를 실행하는 데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역이다.

모든 코드는 실행 컨텍스트를 통해 실행되고 관리된다.

식별자와 스코프는 실행 컨텍스트의 렉시컬 환경 (Lexcial Environment)]]으로 관리하고 코드 실행 순서는 실행 컨텍스트 스택으로 관리한다.

실행 컨텍스트 스택

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

위에서 봤던 예제 코드를 다시 가져왔다. 이 코드는 전역 코드와 지역 함수 코드로 이루어져 있다. 자바스크립트 엔진은 먼저 전역 실행컨텍스트를 생성하고, 함수가 호출되면 함수 코드를 평가하여 함수 실행 컨텍스트를 생선한다. 이렇게 생성된 실행 컨텍스트는 스택 (Stack) 자료구조로 관리된다. 이를 실행 컨텍스트 스택 이라고 부른다.

다음과 같이 실행 컨텍스트 스택에는 실행 컨텍스트가 추가되고 제거된다.
Pasted image 20231015231834.png

  1. 전역 코드의 평가와 실행

    • 전역 코드를 평가하여 전역 실행 컨텍스트를 생성하고 실행 컨텍스트 스택에 푸시한다.
    • 이후 전역 코드가 실행되고, 전역 변수 a에 값1이 할당되고 전역 함수 outer가 호출된다.
  2. outer 함수 코드의 평가와 실행

    • 전역 코드의 실행이 일시 중단되고, 코드의 제어권이 outer함수 내부로 이동한다.
    • outer 함수 내부의 코드를 평가하여 outer 함수 실행 컨텍스트를 생성하고, 실행 컨텍스트 스택에 푸시한다. inner 함수가 outer 함수 실행 컨텍스트의 등록 된다.
    • inner 함수가 호출된다.
  3. inner 함수 코드의 평가와 실행

    • outer 함수 코드의 실행이 일시 중단되고, 코드의 제어권이 inner 함수 내부로 이동한다.
    • inner 함수 내부의 코드를 평가하여 inner 함수 실행 컨텍스트를 생성하고 실행 컨텍스트 스택에 푸시한다.
    • 지역 변수 a가 선언되어 inner 함수 실행 컨텍스트에 등록된다.
    • 먼저, console.log('1. a는 = ', a);를 실행한다. 먼저 a를 참조하기 위해 inner 함수 실행 컨텍스트에서 a를 찾는다. 지역 변수 a가 선언되어 있지만, 할당은 되어있지 않기 때문에 undefined를 출력한다.
    • inner 함수를 종료한다.
  4. outer 함수로 복귀

    • inner 함수가 종료되어 inner 함수 실행 컨텍스트를 실행 컨텍스트 스택에서 제거한다.
    • console.log('2. a는 = ', a);를 실행한다. a를 참조하려 했지만 outer 함수 실행컨텍스트에는 a가 존재하지 않는다. 따라서 상위 스코프인 전역 스코프에서 a를 참조해온다. 따라서 1을 출력한다.
  5. 전역 코드로 복귀

    • outer 함수가 종료되어 outer 함수 실행 컨텍스트를 실행 컨텍스트 스택에서 제거한다.
    • console.log('3. a는 = ', a);를 실행한다. 전역 실행 컨텍스트에 등록된 a에서 값을 참조하여 1을 출력한다.
    • 그리고 더 이상 실행할 전역 코드가 남아 있지 않으므로 전역 실행 컨텍스트도 실행 컨텍스트 스택에서 제거하고 프로그램을 종료한다.

이처럼 실행 컨텍스트 스택은 코드의 실행 순서를 관리한다. 실행 컨텍스트 최상위에 존재하는 실행 컨텍스트는 언제나 현재 실행 중인 코드의 실행 컨텍스트다.

따라서 실행 컨텍스트 스택의 최상위에 존재하는 실행 컨텍스트를 실행 중인 실행 컨텍스트라 부른다.


참조