안녕하세요.
오늘은 실행 컨텍스트라는 개념에 대해 알아보겠습니다.
🔸 실행 컨텍스트란?
실행 컨텍스트는 실행할 코드에 대한 모든 정보를 모아 놓은 객체입니다.
자바스크립트 엔진은 실행 가능한 코드를 만나면 그 코드를 평가한 후에 실행 컨텍스트를 생성합니다.
* 실행 가능한 코드란? 전역 공간, 함수, eval() 함수. (실행 가능한 코드 별로 실행 컨텍스트가 생성됨)
🔸 프로그램 실행과 실행 컨텍스트
이 실행 컨텍스트는 언제 사용되는 걸까요?
프로그램이 평가된 후에 프로그램이 실행되는데, 이 프로그램이 실행 컨텍스트 안에서 실행됩니다.
실행 컨텍스트는 스택이라는 구조로 관리되어, 전체코드의 환경과 순서를 보장합니다.
* 스택이란? 자료 구조의 하나로, 데이터를 아래에서부터 쌓아 올린 후에, 가장 마지막에 추가한 데이터를 먼저 꺼내는 구조입니다.
아래 그림의 경우 a -> b -> c -> d 순서로 데이터를 넣었고, d -> c -> b -> a 순서로 데이터를 꺼낼 수 있습니다.

예제를 통해 실제로 실행 컨텍스트가 어떤 순서로 쌓이고, 어떤 순서로 코드 실행에 관여하는지 확인해봅시다.
var a = 1;
function outer(){
function inner(){
console.log(a);
var a = 3;
}
inner();
console.log(a);
}
outer();
console.log(a);
1. 자바스크립트 코드를 실행하는 순간 전역 컨텍스트가 콜 스택에 담깁니다.
2. outer 함수를 호출하면 자바스크립트 엔진은 outer에 대한 환경 정보를 수집해서 outer 실행 컨텍스트를 생성한 후 콜 스택에 담습니다.
(콜 스택의 맨 위에 outer 실행 컨텍스트가 놓인 상태이므로 전역 컨텍스트와 관련된 코드 실행을 일시정지한 후 outer 실행 컨텍스트와 관련된 코드를 실행)
3. outer 함수 안에서 호출한 inner 함수의 실행 컨텍스트가 콜 스택의 가장 위에 담깁니다.
(콜 스택의 맨 위에 inner 실행 컨텍스트가 놓인 상태이므로 outer 컨텍스트와 관련된 코드 실행을 일시정지한 후 inner 실행 컨텍스트와 관련된 코드를 실행)
4. inner 함수 내부에서 a 변수에 3을 할당하고 나면 inner 함수의 실행이 종료되면서 inner 실행 컨텍스트가 콜 스택에서 제거됩니다.
5. 아래에 있던 outer 컨텍스트의 중단 지점부터 다시 실행하여 변수 a 값을 출력합니다. outer 함수의 실행이 종료되어 outer 실행 컨텍스트가 콜 스택에서 제거됩니다.
6. 중단했던 전역 컨텍스트 지점부터 다시 실행하여 변수 a 값을 출력합니다.
전역 공간에 실행할 코드가 남아있지 않아 전역 컨텍스트도 제거되고, 콜 스택에는 아무것도 남지 않은 상태로 종료됩니다.

🔸 실행 컨텍스트 구성
실행 컨텍스트가 실행되는 순서에 대해 알아보았으니, 이제는 실행 컨텍스트에 어떤 정보가 담기는지에 대해서 알아봅시다. 실행 컨텍스트는 크게 3가지로 구성되어 있습니다.
- VariableEnvironment
현재 컨텍스트 내의 식별자들에 대한 정보(Environment Record), 외부 환경정보(Outer Environment Reference) 정보를 담고 있음. 초기에는 LexicalEnvironment와 동일한 값을 가지지만, 변경 사항이 반영되지 않음.
- LexicalEnvironment
현재 컨텍스트 내의 식별자들에 대한 정보(Environment Record), 외부 환경정보(Outer Environment Reference) 정보를 담고 있음. 변경 사항이 반영됨.
- ThisBinding
그 함수를 호출한 객체의 참조가 저장됨.
실행 컨텍스트 구성 정보를 의사 코드로 나타내면 다음과 같습니다.
ExecutionContext = {
LexicalEnvironment : {
EnvironmentRecord : {},
OuterEnvironmentReference : {},
},
VariableEnvironment : {
EnvironmentRecord : {},
OuterEnvironmentReference : {},
},
ThisBinding : null,
}
🔸 Environment Record와 호이스팅
실행 컨텍스트 구성 정보 중 중요한 역할을 하는 Environment Record에 대해 더 알아보겠습니다.
Environment Record에는 현재 컨텍스트와 관련된 식별자 정보들이 저장됩니다.
* 식별자 정보 : 매개변수, 함수 선언문으로 생성한 함수 그 자체, 선언한 변수
변수 정보 수집이 끝난 후에도 아직 코드는 실행되기 전의 상태입니다. 코드가 실행되기 전이지만 자바스크립트 엔진은 이미 지역 변수 또는 함수 선언문으로 선언한 함수 이름을 모두 알고 있는 것입니다. 여기서 호이스팅 개념이 등장하게 됩니다.
자바스크립트 엔진이 실제로 식별자들을 끌어올리지는 않지만, 이해하기 쉬운 방법으로 대체한 가상의 개념입니다.
* 호이스팅이란? 자바스크립트 엔진은 식별자들을 최상단으로 끌어올린 다음 실제 코드를 실행한다는 개념입니다.
* 호이스팅 대상 : 함수 선언문으로 선언한 함수, let, var, const 로 선언한 변수.
(var로 선언한 변수는 undefined로 초기화하지만, let, const는 초기화하지 않음) https://developer.mozilla.org/ko/docs/Glossary/Hoisting
호이스팅은 중요한 개념이므로, 간단한 예제를 통해 이해하는 시간을 가져보겠습니다.
function a(b){
console.log(b);
var b = 'bbb';
console.log(b);
function b(){}
console.log(b);
}
a(1);
위 코드를 수행하면 console에 어떤 내용이 보일까요? 단계별로 코드를 변형하여 알아보겠습니다.
함수를 인자와 함께 호출할 때는, 인자를 함수 내부의 다른 코드보다 먼저 선언, 할당이 이루어진 것으로 간주할 수 있습니다. 그렇게 코드를 바꿔보겠습니다.
function a(){
var b = 1;
console.log(b);
var b = 'bbb';
console.log(b);
function b(){}
console.log(b);
}
a();
여기서 한 단계 더 나아가, 호이스팅 개념을 적용하여 코드를 변경해보겠습니다.
function a(){
var b = 1;
var b;
var b = function b(){};
console.log(b);
b = 'bbb';
console.log(b);
console.log(b);
}
a();
바뀐 코드를 보면 console에 나타날 내용을 쉽게 유추할 수 있습니다.
여기까지 Environment Record와 호이스팅에 대해 알아보았습니다.
🔸 식별자 결정과 OuterEnvironmentReference
다음은 식별자 결정과 OuterEnvironmentReference에 대해 알아보겠습니다.
식별자 결정 규칙에 대해 알아보기 전에 스코프란 개념부터 알아보겠습니다.
스코프란?
식별자의 유효범위를 말합니다.
전역 변수의 유효 범위는 코드 전체이고, 함수 안에 있는 지역 변수의 유효 범위는 함수 안에 있는 전체 코드입니다.
식별자 결정 규칙
아래 코드의 경우, 변수 a의 유효 범위는 코드 전체이고, 변수 b의 유효 범위는 함수 f 안이라는 것입니다.
let a = 1;
function f(){
let b = 2;
}
이때 아래와 같이 변수 b를 함수 f 밖에서 사용하려고 하면,
let a = 1;
function f(){
let b = 2;
}
console.log(b)
Reference Error가 발생하게 됩니다. 변수 b의 유효범위는 함수 f 안이기 때문입니다.
반대로 변수 a를 함수 f 안에서 사용하게 되면, 정상적으로 처리되는 것을 보실 수 있습니다.
let a = 1;
function f(){
let b = 2;
console.log(a)
}
f();
변수 a의 유효범위가 코드 전체이기 때문입니다.
이 때 함수 f 안에서는 변수 a가 없는데 어떻게 전역 환경의 변수 a를 참조하는 것일까요?
바로 OuterEnvironmentReference가 변수 a를 찾는 것을 도와주기 때문입니다.
OuterEnvironmentReference란?
outerEnvironmentReference는 현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조합니다.
위의 코드 같은 경우 함수 f는 전역 환경에서 호출되었기 때문에, f의 outerEnvironmentReference는 전역 환경의 LexicalEnvironment를 참조하게 되는 것입니다. 그래서 전역 환경의 변수 a를 사용할 수 있게 된 것이죠.
🔸 ThisBinding
드디어 마지막으로 ThisBinding에 대해서 알아보겠습니다.
자바스크립트에서 this는 실행 컨텍스트가 생성될 때 결정됩니다. 함수가 호출되었을 때 그 함수가 속해 있던 객체를 참조하게 됩니다.
실행 컨텍스트의 ThisBinding에서는 이 정도까지만 알아보고, this 개념에 대해서는 따로 글을 작성하도록 하겠습니다.
오늘 실행 컨텍스트에 대해 알아보았는데요, 정말 복잡하면서도.. 자바스크립트의 특징을 이해하기 위해서는 필수로 알아두어야 하는 개념인 것 같습니다!
오늘도 도움이 되었길 바라며, 이만 마치겠습니다.
궁금한 점이 있으시면 댓글로 문의 부탁드립니다~ 감사합니다
출처 : 코어 자바스크립트, 모던 자바스크립트 입문
'Frontend > Javascript' 카테고리의 다른 글
[Javascript] Prototype 프로토타입 (0) | 2022.04.10 |
---|---|
[Javascript] Promise (0) | 2022.04.04 |
[Javascript] Garbage Collection (0) | 2022.03.22 |
[Javascript] Closure 클로저 (0) | 2022.03.17 |
[Javascript] this (0) | 2022.03.09 |