
오늘은 자바스크립트의 실행 컨텍스트에 대해 배운 내용을 정리해 보았다.
실행 컨텍스트란 코드 실행에 필요한 환경 정보들을 담고 있는 객체를 의미한다. 이렇게 말하면 너무 어렵기 때문에 조금 더 쉽게 설명을 해보자면 요리에 비유할 수 있다.

실행 컨텍스트는 요리사가 음식을 만들기 전 필요한 모든 재료와 도구를 준비해둔 주방과 같은 역할을 한다. 그리고 어떤 요리를 하느냐에 따라 재료와 도구가 다르듯이 실행 컨텍스트도 실행되는 코드에 따라 구성 요소가 달라진다.
자바스크립트는 실행 컨텍스트가 활성화되는 시점에 호이스팅, 외부 환경 정보 구성, this 값 설정이라는 중요한 작업을 수행한다.
실행 컨텍스트는 콜스택 자료구조를 이용해 관리되기 때문에 스택에 대한 이해가 필요하다.
스택은 LIFO(Last In, First Out) 구조로 가장 나중에 들어간 것이 가장 먼저 나오는 특성을 가지고 있다.

(출처: https://ko.wikipedia.org/wiki/%EC%8A%A4%ED%83%9D)
간단한 예제 코드를 보면서 실행 컨텍스트가 어떻게 동작하는지 살펴볼 수 있다.
var a = 0; // (1)
function outer() {
function inner() {
console.log(a);
var a = 1;
}
inner(); // (3)
console.log(a);
}
outer(); // (2)
console.log(a);
위 코드는 다음과 같은 순서로 실행된다.
1. (1) 전역 컨텍스트가 콜스택에 들어간다.
2. (2) outer() 함수 호출 시, outer 컨텍스트가 콜스택에 추가된다.
3. (3) inner() 함수 호출 시, inner 컨텍스트가 콜스택에 추가된다.
4. 함수 실행이 끝날 때마다 콜스택에서 빠져나간다. 즉, inner -> outer -> 전역 추가된 역순으로 콜스택에서 빠져나가게 된다.

실행 컨텍스트의 구성은 다음과 같다.
VariableEnvironment와 LexicalEnvironment는 매우 유사하지만 차이점이 있다.
VE의 경우 선언된 시점의 정보를 스냅샷으로 유지한다. 즉, 선언되었을 시점 그대로를 사진찍어서 가지고 있다고 생각하면 이해하기 쉽다.
반면, LE의 경우 변경되는 정보가 실시간으로 반영된다.
따라서, 우리는 실시간으로 정보가 반영되는 LE를 주로 사용하게 된다.
LE를 보다 자세히 알기 위해 호이스팅과 스코프 체인의 개념에 대해서 이해하여야 한다.
우선 호이스팅은 컨텍스트 내의 식별자 정보인 record와 관련이 있다.
호이스팅은 인터프리터가 코드를 실행하기 전에 함수, 변수, 클래스 등의 선언문을 맨 위로 끌어올리는 것처럼 보이는 현상을 의미한다.
다음 코드는 호이스팅이 어떻게 적용되는지 보여주는 간단한 예제이다.
function a () {
var x = 1;
console.log(x); // 예상: 1
var x;
console.log(x); // 예상: undefined
var x = 2;
console.log(x); // 예상: 2
}
a();
함수의 실행 과정을 보았을 때 1, undefined, 2가 출력될 것이라고 예상된다.
위 코드를 호이스팅된 형태로 풀어보면 다음과 같다.
function a() {
var x;
var x;
var x;
// 변수 선언문은 모두 호이스팅되어 위로 끌어올려진다.
x = 1;
console.log(x);
console.log(x);
x = 2;
console.log(x);
}
a();
이와 같이 변수 선언문이 함수 내에서 맨 위쪽으로 호이스팅되기 때문에 var = x가 우선적으로 모두 실행되고 이후 식별자에 할당하는 코드가 진행되어 결과는 1, 1, 2가 된다.
스코프란 식별자에 대한 유효범위를 의미한다.
LE의 구성 요소인 outer는 외부 변수를 기억하고 사용할 수 있도록 돕는 스코프 체인을 가능하게 한다.
var a = 1;
var outer = function() {
var inner = function() {
console.log(a); // (1)
var a = 3;
};
inner();
console.log(a); // (2)
};
outer();
console.log(a); // (3)
var a 선언 부분이 호이스팅되기 때문에 다음 코드와 같이 undefined가 출력된다.var inner = function() {
var a;
console.log(a);
a = 3;
}
(2): 현재 outer 컨텍스트 내부에는 a라는 변수가 없기 때문에 타고 올라가서 전역 컨텍스트의 LE를 참조하게 된다. 따라서 전역 컨텍스트에 있는 a = 1을 참조하여 1이 출력된다.
(3): 전역 컨텍스트의 a값인 1이 출력된다.
콜스택은 LILO 구조를 가지고 있기 때문에 inner함수가 가장 늦게 콜스택에 들어오지만 가장 먼저 빠져나가게 된다.
따라서, outer함수가 실행될 때는 inner 컨텍스트가 콜스택 내부에 존재하지 않아서 var a = 3;을 참조할 수 없다. 대신, outer 컨텍스트 이전에 들어온 전역 컨텍스트가 아직 콜스택 내부에 존재하기 때문에 이를 참조할 수 있다.
스코프 체인은 변수를 검색할 때 스코프의 계층 구조를 따라 차례대로 거슬러가며 참조하는 구조를 말한다.
[참고문헌]
https://medium.com/hcleedev/web-javascript의-실행-컨텍스트-lexicalenvironment-scop-ce664aa2076
https://velog.io/@sj_yun/스코프-스코프-체인