실행 컨텍스트
프로그래밍 언어의 실행 방법

-
Hello World
를 출력하는 기계어 -
컴파일러 : 컴파일러를 통해 컴파일 타임에 전체 소스 코드를 한 번에 기계어로 변환 후 실행파일을 만든다. 컴파일러 언어는 컴파일 단계와 실행 단계가 각각 분리되어 있으며, 컴파일은 단 한번만 수행한다. c언어는 코드를 바로 실행하지 못한다. 코드 파일(hello.c)을 컴파일러를 통해 hello 파일을 만들어 변환 후 이를 실행하면, 컴퓨터가 출력하는 것을 확인할 수 있다.
-
인터프리터: 인터프리터 언어는 소스 코드를 한번에 기계어로 변환하는 컴파일러와 달리, 컴파일 하지 않고 소스 코드를 한 줄씩 읽어들여 실행한다. 컴파일 하는 과정이 없기 때문에 컴파일 하는 시간은 소요되지 않으나, 인터프리터 언어는 실행파일을 별도로 생성하지 않기 때문에 실행 시마다 인터프리터 과정이 반복 수행되어 실행 속도가 느리다는 단점이 있다.
-
V8 과 같은 자바스크립트엔진은 번역기 역할을 수행하는 인터프리터로 프로그래밍 언어를 컴퓨터가 해석할 수 있도록 도와준다. 실행 컨텍스트는 자바스크립트 엔진이 코드를 어떻게 읽고 실행하는 지에 대한 방법이다.
-
코드 평가, 선언문을 읽는 것은 전체 코드를 슥 훑어 보는 것으로 진행한다. 이후 코드 한 줄씩 실행하며 실행 결과를 받아온다.

실행 컨텍스트?
- ⌈모던 자바스크립트 Deep Dive⌋ 와 정재남님의 모던 자바스크립트 Deep Dive 강좌를 참고하여 만들었습니다. ES5 에서는 Execution Context 바로 하위에 thisBinding. ES6 에서는 E.C에서 빠지고 Environment Record 하위에 This Binding
코드가 실행되기 위해서는 스코프, 식별자, 코드 실행 순서 등을 관리해주어야 할 무언가가 필요합니다.! 이렇게 자바스크립트에서 코드 실행을 관리해주는 것이 실행 컨텍스트입니다. 얘를 잘 알면, 호이스팅, 스코프, 클로저 등을 이해하기 쉽습니다.!
- 실행 컨텍스트를 만들 수 있는 방법으로는 전역공간, 함수, eval() 함수가 있습니다. 이 중에서 eval 함수는 없다고 생각하자. (문자열로 된 자바스크립트 코드를 전달하면 그게 그대로 실행되는 함수인데, 속도나 보안이 좋지 않아 현재는 거의 쓰지 않습니다.)
- 실행 컨텍스트는 소스코드를 실행하는 데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역이다. 즉 모든 코드는 실행 컨텍스트를 통해 실행되고 관리.
- 실행 컨텍스트는 크게 Lexical Environment 와 Variable Environment로 나누어 집니다.
- VariableEnvironment : 현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보. 선언 시점의 LexicalEnvironment의 스냅샷으로, 변경사항은 반영되지 않음
- LexicalEnvironment : 처음에는 VariableEnvironment와 같지만 변경사항이 실시간으로 반영됨. 식별자와 스코프는 렉시컬 환경으로 관리한다.
- 코드 실행 순서는 실행컨텍스트의 스택(작동 방식)으로 관리합니다.
렉시컬 환경
- 식별자와 식별자에 바인딩 된 값, 상위 스코프에 대한 참조를 기록하는 자료구조로 실행 컨텍스트를 구성하는 컴포넌트입니다.
- 특정 코드가 작성, 선언(정의)된 환경을 의미합니다. Lexical이라는 단어 자체의 뜻이 '사전의, 본질적인, 정의된' 이므로 이와 연관시켜 생각할 수도 있습니다.
- 렉시컬 환경은 변수, 함수 등이 어떤 렉시컬 환경에 속해있는지에 따라 이용 가능한 변수가 달라집니다. 즉 어떤 변수나 함수의 값은 이를 '어디에서 호출했는지' 가 아니라, '어디에서 선언했는지' 즉 렉시컬 환경이 어디인지에 따라서 결정됩니다.
- 렉시컬 환경은두 개의 컴포넌트로 구분이 됩니다.
- 환경 레코드 : 스코프에 포함된 식별자를 등록하고 등록된 식별자에 바인딩된 값을 관리하는 저장소다. 환경 레코드는 소스코드의 타입에 따라 관리하는 내용에 차이가 없다. (현재 컨텍스트에서 선언된 변수 및 함수가 담겨있다.) - 외부 렉시컬 환경에 대한 참조 : 외부 렉시컬 환경에 대한 참조는 상위 스코프를 가리킨다. 이때 상위 스코프란 외부 렉시컬 환경, 즉 해당 실행 컨텍스트를 생성한 소스코드를 포함하는 상위 코드의 렉시컬 환경을 말한다. 외부 렉시컬 환경에 대한 참조를 통해 단방향 링크드 스코프 체인을 구현. (상위 컨텍스트의 함수나 변수를 참조)
스택
LIFO(Last In First Out), 밑에서부터 위로 쌓여서, 가장 최근에 쌓인 녀석이 먼저 나가는 구조입니다! 그렇다면, 실행 컨텍스트에서 말하는 스텍은 무엇일까? 이는 코드 실행의 순서가 스택과 같다는 것을 의미합니다.

따라서 실행 컨텍스트 스택의 최상위에 존재하는 실행 컨텍스트는 언제나 현재 실행 중인 코드의 실행 컨텍스트입니다.
실행 컨텍스트의 과정
var x = 1;
const y = 2;
function foo(a) {
var x = 3;
const y = 4;
function bar(b) {
const z = 5;
console.log(a + b + x + y + z);
}
bar(10);
}
foo(20); // 42
1. 전역 실행 컨텍스트 생성
var x = 1;
// ---------------- const Y에대한 TDZ -------------------
const y = 2;
function foo (a) {

- 우선 전역 실행 컨텍스트를 생성합니다.
- 선언문으로 정의된 (var x, function foo)는 환경 레코드의 객체 환경 레코드에 묶인다. 변수는 변수 호이스팅에 의해 undefined로 초기화 되고 함수는 함수 호이스팅을 통해 바로 접근 할 수 있습니다.
- 이를 통해 전역 컨텍스트에서 객체로 등록이 되어 전역 객체를 가리키는 식별자(window) 없이 전역 객체의 프로퍼티를 참조할 수 있습니다. (ex. window.alert, alert)
- 반면에 let과 const로 선언된 변수는 객체 환경 레코드에 바인딩 되지 않는다. 선언적 환경 레코드에 등록되고 관리됩니다.
- 이때 const로 등록된 변수 y는 런타임 과정에서 변수 선언문에 도달하기 전까지 일시적 사각지대(TDZ : Temporal Dead Zone)에 빠지게 된다. 위의
<uninitialized>
는 초기화 단계가 진행되지 않아 변수에 접근할 수 없음을 나타내기 위해 사용되었습니다. - 일반적으로 전역 객체에서 this를 참조하면 window가 묶이므로 객체 환경 레코드가 바인딩 됩니다.
- 전역 실행 컨텍스트에서 현재 소스코드를 포함하는 외부 소스코드의 렉시컬 환경, 상위 스코프는 없기 때문에 null이 할당됩니다.
2. 전역 실행 컨텍스트 실행
- 이후 전역 코드가 실행되면서 const y, var x에 1,2가 할당된다. 이제 const로 선언된 변수에 접근할 수 있게됩니다.

3. foo 함수 코드 (코드 평가 단계 생략)
- 실행 컨텍스트는 스택으로 관리되고 있습니다. 따라서 코드 실행중 foo 함수를 만나게 되면 foo 함수 실행 컨텍스트가 전역 컨텍스트 위에 쌓이게 됩니다.
function foo(a) {
var x = 3;
const y = 4;
function bar(b) {
const z = 5;
console.log(a + b + x + y + z);
}
bar(10);
}

- 함수 내의 var 선언과 내부 함수 bar 선언, 매개변수 a는 foo 함수 실행 컨텍스트의 환경 레코드에 기록된다.
- const로 선언된 y 또한 환경 레코드에 기록됩니다. (함수 실행 컨텍스트는 환경레코드를 구분하지 않습니다.)
- foo는 일반 함수로 호출되었으므로 this는 전역 객체를 가리킵니다.
- 외부 렉시컬에 대한 환경 변수는 전역 실행 컨텍스트의 전역 렉시컬 환경의 참조가 이루어집니다.
- 이제 런타임이 실행되어 foo 함수의 코드가 순차적으로 실행됩니다.
4. bar 함수 코드
function bar(b) {
const z = 5;
console.log(a + b + x + y + z);
}

console.log(a + b + x + y + z);
를 실행하기 위해 스코프 체인에서 검색합니다.- z: 5, b: 10은 Bar 실행 컨텍스트에서 찾습니다.
- a, x, y 변수는 bar 실행 컨텍스트에 없기에 외부 렉시컬 환경 참조에 의해 foo 컨텍스트를 참조합니다.
- a:20, x:3, y:4 인 것을 인지합니다.
- 위의 코드 실행 결과는 5+10+20+3+4 = 42를 호출합니다.
5. 실행 종료
- 스택의 방식으로 bar 실행 컨텍스트부터, 종료되어 global 실행 컨텍스트 까지 종료하게 되면 코드 실행이 마무리됩니다. 이후 스택에는 아무것도 남지 않게 됩니다.
참조
자바스크립트의 실행 컨텍스트 (execution context)
- 프로그래밍 언어의 실행 방법
- 실행 컨텍스트?
- - 렉시컬 환경
- - 스택
- 실행 컨텍스트의 과정
- - 1. 전역 실행 컨텍스트 생성
- - 2. 전역 실행 컨텍스트 실행
- - 3. foo 함수 코드 (코드 평가 단계 생략)
- - 4. bar 함수 코드
- - 5. 실행 종료
- 참조