- 실행 컨텍스트는 복합적인 개념을 포함하고 있기 때문에, 이번 Section에서는 개념을 환기할 수 있는 예시를 들어가며, 실행 컨텍스트의 내용에 접근해 볼 거에요.
- 설명은 아래의 순서로 진행하도록 할게요!
> 자바스크립트 코드 수행에 따른 콜 스택 상황 파악하기
> 환경 레코드의 개념과 호이스팅과의 연관성 파악하기
> Outer와 스코프체인의 연관성 파악하기
> 이전 과정으로부터 분석한 내용을 토대로 실행 컨텍스트 개념 정리하기
- 해당 Section에서는 자바스크립트 코드의 실행에 따라 콜 스택이 어떻게 동작하는 지에 대한 예시를 들면서 환기할 예정이에요.
- 비동기 처리를 포함한 이벤트 루프와 관련된 사항은 나중에 다뤄보도록 할게요!
- 지금부터는 실행 컨텍스트라는 용어를 사용할텐데, 일단 "실행 컨텍스트는 뭔지 잘 모르겠지만, 여기에는 환경 레코드와 Outer라는 게 들어가는구나!" 라고 이해해주시면 되요!


자바스크립트 코드를 실행시키면, 자바스크립트 엔진은 콜 스택(Call Stack)이라는 통에 전역 실행 컨텍스트를 담아요.
여기서 콜 스택이란, 자바스크립트 코드가 실행되며 생성되는 실행 컨텍스트를 저장하는 자료 구조를 의미해요.
전역에서 함수 a를 실행시키면, 함수 a의 실행 컨텍스트를 생성해 콜 스택에 담아요.
이 때, 콜 스택 안에는 가장 최근에 추가된 실행 컨텍스트(함수 a의 컨텍스트)만 활성화되게 됩니다.
함수 a에서 함수 b가 호출되면, 또 콜 스택에 함수 b의 실행 컨텍스트를 생성해 담습니다.
이 때, 함수 b의 실행이 종료되면 콜 스택에서 함수 b의 실행 컨텍스트는 사라집니다.
마찬가지로, 함수 a가 종료되면 콜 스택에서 함수 a의 실행 컨텍스트도 사라집니다.
전역 코드가 마지막 라인까지 실행되면, 전역 실행컨텍스트도 콜 스택에서 사라집니다
- 호이스팅 현상이 발생하는 이유는 선언문이 있는 코드라인을 물리적으로 최상단으로 끌어올린 게 아니라, 자바스크립트 엔진이 먼저 전체 코드를 스캔하면서 변수같은 정보를 실행 컨텍스트 어딘가에 미리 기록해놓기 때문이에요.
- 이 때 정보를 기록해 놓는곳이 환경 레코드(environment record)이고, 이는 식별자와 식별자에 바인딩된 값을 기록해두는 객체라고 이해하시면 되요.
- 호이스팅이 무엇인지 잘 모르겠다면, "여기"를 클릭해주세요.


자바스크립트 엔진은 코드를 실행하면, 우선 전역 실행 컨텍스트를 생성해 콜 스택에 넣습니다.
그 후 전체 코드를 살펴보며, 선언할 식별자들이 있는지 찾아보고, 있다면 먼저 선언해둡니다.
선언하는 과정에서 생성해둔 실행 컨텍스트 안에 있는 환경 레코드에 새로운 식별자를 기록합니다. 그리고, 이 식별자는 var로 선언한 변수이기 때문에 undefined로 값을 초기화합니다.
여기까지와 앞으로의 단계를 이 시점에서 한 번 정리해볼게요.
Line 1에서 console.log() 수행 시, 환경 레코드에 기록해 둔 name 식별자의 값을 출력합니다. 이 때, 할당문을 만나기 전이기 때문에, undefined가 출력됩니다.
이 때, console.log()도 함수이기 때문에, 해당하는 실행 컨텍스트가 콜 스택 내부에 추가되었다가 함수 실행 후 사라지게 됩니다.
Line 2에서 식별자 name에 대한 할당문을 만나면, 선언은 아까 생성 단계에서 이미 진행하였으니, 이 라인에서는 식별자 name에 대해 값의 할당만 이루어집니다.
Line 3에서 console.log() 수행 시, 환경 레코드에 기록해 둔 name 식별자의 값을 출력합니다. 이 때, 할당문 var name='Lee' 를 만난 후이기 때문에 'Lee'가 출력됩니다.
마찬가지로 console.log()도 함수이기 때문에, 해당하는 실행 컨텍스트가 콜 스택 내부에 추가되었다가 함수 실행 후 사라지게 됩니다.

자바스크립트 엔진은 코드를 실행하면, 우선 전역 실행 컨텍스트를 생성해 콜 스택에 넣습니다.
그 후 전체 코드를 살펴보며, 선언할 식별자들이 있는지 찾아보고, 있다면 먼저 선언해둡니다.
선언하는 과정에서 생성해둔 실행 컨텍스트 안에 있는 환경 레코드에 새로운 식별자를 기록합니다.
이 때, 이 식별자는 const로 선언한 변수이기 때문에 값을 초기화하지 않습니다.
Line 1에서 console.log() 수행 시, 환경 레코드에 기록해 둔 name 식별자의 값을 출력합니다.
이 때, 식별자는 초기화되지 않았기 때문에 ReferenceError가 발생합니다.


자바스크립트 엔진은 코드를 실행하면, 우선 전역 실행 컨텍스트를 생성해 콜 스택에 넣습니다.
그 후 전체 코드를 살펴보며, 선언할 식별자들이 있는지 찾아보고, 있다면 먼저 선언해둡니다.
자바스크립트의 함수는 변수에 담을 수 있습니다. 변수에 담긴 함수는 변수 호이스팅처럼 동작합니다.
선언하는 과정에서 생성해둔 실행 컨텍스트 안에 있는 환경 레코드에 새로운 식별자를 기록합니다.
함수 실행 시, 이제 아래의 문제가 발생합니다.


자바스크립트 엔진은 코드를 실행하면, 우선 전역 실행 컨텍스트를 생성해 콜 스택에 넣습니다.
그 후 전체 코드를 살펴보며, 선언할 식별자들이 있는지 찾아보고, 있다면 먼저 선언해둡니다.
자바스크립트 엔진은 함수 선언문을 발견함과 동시에, 완성된 함수 객체를 생성해 환경 레코드에 기록해둡니다.
이렇게, 함수 선언문으로 함수를 선언하는 경우에는, 선언과 동시에 함수가 생성되어 선언 전에도 함수를 실행할 수 있다는 특징이 있습니다.
함수 선언문을 이용한다면, 함수 실행 시 문제가 발생하지 않습니다.
- 위에서 배운 환경 레코드가 호이스팅과 관련이 되었다면, 지금부터 배울 Outer(Outer environment Reference)는 스코프 체인과 관련된 내용이에요.
- Outer는 현재 호출된 함수가 선언될 당시의 외부 Lexical Environment를 참조해요.
- Lexical Environment 는 코드 블록, 함수 등을 실행하기 앞서 생성되는 특별한 객체로, 실행할 스코프 범위 안에 있는 변수와 함수를 프로퍼티로 저장하는 객체에요. 즉, 소스 코드를 실행하면서 참조가 필요한 변수나 함수가 있다면, 이 객체에서 찾는다고 기억하시면 되요.


자바스크립트 엔진은 코드를 실행하면, 우선 전역 실행 컨텍스트를 생성해 콜 스택에 넣습니다.
이 때, 전역 실행 컨텍스트에 선언된 isPerson=false, goTo2F()의 정보를 전역 실행 컨텍스트의 환경 레코드에 담습니다.
함수 goto2F실행 시, 새로운 실행 컨텍스트가 생성됩니다.
이 때, 함수 goto2F 스코프 내에 선언되어있는 정보를 실행 컨텍스트의 환경 레코드에 기록합니다.
동시에, 자바스크립트 엔진은 새로 생성된 실행 컨텍스트에 바깥 렉시컬 환경으로 돌아갈 수 있는 outer를 남겨놓습니다.
함수 goto3F실행 시, 새로운 실행 컨텍스트가 생성됩니다.
마찬가지로, 함수 goto3F 스코프 내에 선언되어있는 정보를 실행 컨텍스트의 환경 레코드에 기록하고, outer를 함께 남겨놓습니다.
함수 goto3F의 실행문을 수행합니다.
console.log(pet)을 수행하면 같은 스코프 내에 적합한 pet이라는 식별자가 있기 때문에, pet에 있는 cat이라는 값을 바로 출력합니다.
console.log(isPerson)의 경우, 스코프 내에 적합한 식별자가 없기 때문에 outer가 가리키는 바깥 렉시컬 환경(상위 스코프)으로 이동하여, 다시 isPerson이라는 식별자를 탐색합니다.
함수 goto2F의 환경으로 이동하여, isPerson 식별자를 찾은 후, true를 출력합니다.
이 때, 자바스크립트 엔진은 전역 실행 컨텍스트의 isPerson 식별자가 저장된 위치까지 이동하여 파악하는 과정을 거치지는 않습니다. 이렇게, 동일한 식별자로 인해 상위스코프에서 선언한 식별자 값이 가려지는 현상을 변수 섀도잉이라고 합니다.
그리고, outer가 가리키는 렉시컬 환경으로 이동하면서, 식별자를 결정할 때 활용하는 스코프의 연결리스트를 스코프 체인이라고 합니다.
- 지금까지 실행 컨텍스트의 개념을 이해하기 위한 예제들을 살펴보았어요.
- 지금 이 Section에서는, 지금까지의 예제를 보며 이해한 내용을 토대로, 실행 컨텍스트라는 게 대체 무엇인지를 알아볼 거에요.
- 마지막이니까 조금만 힘내도록 해요! 😂
실행 컨텍스트는 코드를 실행하는데 필요한 환경 정보들을 제공하는 객체입니다. 여기서 환경이란, 코드 실행에 영향을 주는 조건이나 상태를 의미합니다.
실행컨텍스트는 코드 실행 시, 식별자 결정을 더욱 효율적으로 하기위한 수단으로 이용 가능합니다. (위에서 "변수 섀도잉" 기억나시나요?)
그리고, 실행 컨텍스트는 자바스크립트 코드가 실행되는 환경이기 때문에, 모든 자바스크립트 코드는 실행 컨텍스트 내부에서 실행된다고 볼 수 있습니다. 예를 들어, 함수가 실행되면 함수 실행에 해당하는 실행 컨텍스트가 생성되고, 생성된 실행 컨텍스트는 자바스크립트 엔진에 있는 콜 스택에 차곡차곡 쌓이게 됩니다.
이렇게 실행 컨텍스트는 동일한 환경에 있는 코드들을 실행할 때, 필요한 환경 정보들을 모아 객체를 구성하고 콜 스택에 쌓이게 됩니다. 그리고 자바스크립트 엔진은 콜 스택의 가장 위에 쌓여있는 실행 컨텍스트에 대한 코드들을 실행함으로써, 전체 코드의 환경과 순서를 보장합니다.
전역 영역에 존재하는 코드에 해당하며, 함수 안에서 실행되는 코드가 아니라면 모든 스크립트는 전역 컨텍스트(Global Context)에서 실행됩니다.
스택 구조를 가지는 형태로 실행 컨텍스트가 생성이 된 후, 전역 객체(global object)로 window가 this로 할당된 다음, 콜 스택에 쌓이게 됩니다.
참고로, strict mode가 적용된 this의 default는 undefined입니다.
함수 컨텍스트(Functional Context)는 선언된 함수가 호출이 될 때를 기점으로 생성이 되고, 함수의 모든 동작이 완료되면 소멸됩니다.
각 함수들은 자신만의 Functional Context를 가지지만, 함수가 호출되고 실행이 되어야만 콜 스택에 쌓이게됩니다.
선언 시점에서의 컨텍스트와 관련된 코드의 식별자 정보들을 담는 환경 레코드와 현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조하는 outer를 담습니다.
구성 - EnvironmentRecord, outer-EnvironmentReference
처음에는 VariableEnvironment와 동일하지만, 변경사항이 실시간으로 반영된다는 차이가 있습니다. (함수 실행 도중에 변경되는 사항이 즉시 반영된다는 의미)
구성 - EnvironmentRecord, outer-EnvironmentReference
this 식별자가 바라보고 있는 대상 객체를 저장합니다.
구성 - EnvironmentRecord, outer-EnvironmentReference