실행 컨텍스트
실행 컨텍스트는 자바스크립트가 실행되는 환경이다.
여기서 환경은 this, 변수, 객체, 함수 등 코드의 실행에 필요한 기반들이다.
좀 더 구체적으로 말하자면, 실행 컨텍스트는 코드를 실행하는데 필요한 환경을 제공하고 관리한다.
이 중에서 식별자, 스코프, this 등은 실행 컨텍스트의 렉시컬 환경을 기반으로 관리되고, 코드의 실행순서는 콜스택(실행 컨텍스트의 스택)을 통해서 관리된다.
실행 컨텍스트 종류
1. 전역 실행 컨텍스트
처음으로 자바스크립트 코드가 실행될 때 생성된다.
2. 함수 실행 컨텍스트
함수가 호출될 때마다 생성된다. 각각의 함수 호출은 모두 각자의 실행 컨텍스트를 생성하고 가진다.
3. eval 실행 컨텍스트
strict mode(엄격 모드)에서 독립적인 스코프를 생성한다.
4. 모듈 실행 컨텍스트
모듈별로 독립적인 스코프를 생성한다.
실행 컨텍스트 스택(콜스택)
스택은 선입 선출의 특징을 가진 자료구조이고, 자바스크립트는 스택에 실행 컨텍스트를 순차적으로 추가하고 제거하면서 코드의 순서를 관리하고 실행한다.
const a = 'a';
function foo() {
const b = 'b';
bar();
function bar() {
const c = 'c';
if(true) console.log("Hello, World");
}
}
foo();
해당 코드가 실행 컨텍스트에서 어떻게 저장되고 관리되는지 알아보자.
0. 처음에 실행 컨텍스트 스택은 비어있다.
1. 자바스크립트 코드가 실행되면서 전역 실행 컨텍스트가 생성된다. 전역 스코프에 선언된 변수와 함수 등의 정의가 진행된다.
global |
2. 그다음 foo 함수가 호출되면서 foo 함수의 함수 실행 컨텍스트가 생성된다. 이 안에서 변수 b와 bar 등의 평가와 실행이 진행된다.
foo |
global |
3. foo 함수 안에서 bar를 호출하였기 때문에 bar 함수의 실행 컨텍스트를 생성한다.
bar |
foo |
global |
4. bar 함수의 동작이 완료되었으므로 bar 함수의 실행컨텍스트를 스택에서 제거한다.
foo |
global |
5. foo 함수의 동작이 완료되었으므로 foo 함수를 실행 컨텍스트를 스택에서 제거한다.
foo |
global |
6. 모든 코드의 실행이 종료되었으므로 전역 실행 컨텍스트를 스택에서 제거한다.
평가와 실행
실행 컨텍스트는 종류별로 세부적인 구성요소와 동작이 다르다. 하지만 모든 실행 컨텍스트는 평가와 실행 과정을 거쳐서 생성되고 관리된다.
평가
평가는 실행 컨텍스트를 생성하고 변수, 함수 등의 선언문을 파악하여 현재 스코프 내에서 사용할 수 있는 변수, 함수의 식별자를 실행 컨텍스트에 등록하는 과정이다.
여기서 호이스팅이라는 개념이 나온다. 호이스팅은 식별자가 마치 코드블록의 제일 상위 부분으로 끌어올려지는 것처럼 보이는 현상을 말한다. 사실 실제 자바스크립트 스펙에는 호이스팅이라는 용어가 없다. 하지만 평가 과정에서 식별자들에 대한 정보가 먼저 실행 컨텍스트에 기록된다.
실행
실행은 선언문을 제외한 소스코드를 실행하는 과정이다. 실행 과정에서는 소스코드 실행에 필요한 정보, 즉 변수나 함수의 참조를 실행 컨텍스트에서 찾고 실행과정에서 일어나는 변숫값의 변경 등은 다시 실행 컨텍스트에 등록한다.
실행 컨텍스트 내부
실행 컨텍스트 내부에는 LexicalEnvironment라는 객체가 존재한다. 이 객체는 스코프를 관리하는 역할을 하고, 이 안에 변수, 함수의 정의, 값들이 저장된다.
LexicalEnvironment는 실행 컨텍스트 종류에 따라 조금씩 다르지만 크게 2가지 영역으로 구성되어 있다.
1. EnvironmentRecord(환경 레코드)
식별자를 등록하고 관리하는 역할을 한다.
2. OuterLexicalEnvironmentReference(외부 렉시컬 환경에 대한 참조)
상위 스코프를 참조하는 역할을 한다.
그리고 LexicalEnvironment는 평가과정에서 일반적으로 3가지 동작을 수행한다.
1. 식별자 생성
2. this binding
3. 참조할 외부 환경 결정
그다음 실행과정에서 평가과정에서 생성된 정보들을 기반으로 값들을 변경하는 방식으로 진행된다.
정리
- 실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다.
- 실행 컨텍스트 객체는 활성화되는 시점에 variableEnvironment, LexicalEnvironment, ThisBinding을 수집한다.
- 실행 컨텍스트를 생성할 때는 variableEnvironment와 LexicalEnvironment가 동일한 내용으로 구성되지만, LexicalEnvironment는 함수 실행 도중에 변경되는 사항이 즉시 반영되고, variableEnvironment는 초기 상태를 유지한다.
- variableEnvironment와 LexicalEnvironment는 environmentRecord와 OuterLexicalEnvironmentReference로 구성되어 있다.
- 스코프는 변수의 유효범위를 말하고 OuterLexicalEnvironmentReference는 해당 함수가 선언된 위치의 LexicalEnvironment을 참조한다. 코드 상에서 어떤 변수에 접근하려고 하면 현재 컨텍스트의 LexicalEnvironment를 탐색해서 발견되면 그 값을 반환하고, 발견하지 못하면 OuterLexicalEnvironmentReference에 담긴 LexicalEnvironment를 탐색한다. 전역 컨텍스트의 LexicalEnvironment까지 탐색해도 해당 변수를 찾지 못하면 undefined를 반환한다.
- this에는 실행 컨텍스트를 활성화하는 당시에 지정된 this가 저장된다.
참고자료
- 원티드에서 수강한 프로그램에서 학습한 내용
- 코어 자바스크립트 책
질문이나 잘못된 점은 댓글로 남겨주세요 :)💖
'JavaScript' 카테고리의 다른 글
이벤트 루프 작동 원리 (0) | 2023.06.01 |
---|---|
[JS] 배열에 있는 값을 객체로 만드는 법(키:배열의 값, 값:해당 값의 개수) (0) | 2023.03.28 |
[JS] Promise에서 PromiseResult 데이터 꺼내는 법 (0) | 2023.03.08 |
[JS] JSON(JavasScript Object Notation)에 대해 알아보자 (0) | 2023.02.22 |
[JS] 데이터 속성 사용하기 (data-) (0) | 2023.02.20 |
댓글