Skip to content

Commit 9b6fef4

Browse files
committed
✏️ 6회차 문서 추가 : 실행 컨텍스트
1 parent 34a07bd commit 9b6fef4

1 file changed

Lines changed: 148 additions & 0 deletions

File tree

Javascript/execution_context.md

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
자바스크립트의 동작 원리를 담은 핵심 개념으로, 이를 바르게 이해하면 앞서 배운 자바스크립트 동작과 앞으로 배울 내용을 명확히 알 수 있습니다.
2+
3+
## 소스코드의 타입
4+
> ECMAScript가 정의한 4가지 소스코드 타입입니다. 이들 코드는 **실행 컨텍스트를 생성**합니다.
5+
6+
이렇게 구분하는 이유는 소스코드의 타입에 따라 실행 컨텍스트를 생성하는 과정과 관리 내용이 다르기 때문입니다.
7+
1. 전역 코드(전역에 존재하는 코드)
8+
- 전역 변수를 관리하기 위한 최상위 스코프인 전역 스코프를 생성합니다.
9+
- 전역 코드가 평가되면 전역 실행 컨텍스트가 생성됩니다.
10+
2. 함수 코드(함수 내부에 존재하는 코드)
11+
- 지역 스코프를 생성하고 지역 변수, 매개변수, arguments 객체를 관리합니다.
12+
- 함수 코드가 평가되면 함수 실행 컨텍스트가 생성됩니다.
13+
3. ~~eval 코드~~(사용을 권장하지 않습니다)
14+
- strict mode에서 자신만의 독자적인 스코프를 생성합니다.
15+
- eval 코드가 평가되면 eval 실행 컨텍스트가 생성됩니다.
16+
4. 모듈 코드
17+
- 모듈별로 독립적인 모듈 스코프를 생성합니다.
18+
- 모듈 코드가 평가되면 모듈 실행 컨텍스트가 생성됩니다.
19+
20+
이렇게 놓고 보면, 저희가 선택할 수 있는 타입은 대부분 두 가지가 됩니다. 바로 전역 코드와 함수 코드죠. 이것으로 실행 컨텍스트에 대해 알아 볼 거에요.
21+
22+
<br>
23+
24+
## 소스코드 평가와 실행
25+
> 자바스크립트 엔진은 **소스코드 평가****소스코드 실행** 과정으로 나누어 처리합니다.
26+
27+
소스코드 평가 과정은 이렇습니다.
28+
1. 실행 컨텍스트 생성
29+
2. 변수, 함수 등의 선언문만 먼저 실행
30+
3. 생성된 변수나 함수 식별자를 키로 실행 컨텍스트가 관리하는 스코프에 등록
31+
- 여기서의 스코프는 렉시컬 환경의 환 경 레코드라고 합니다.
32+
33+
소스코드 평가 과정이 종료되면 소스코드가 실행되는, `런타임`이 시작됩니다.
34+
1. 선언문을 제외한 소스코드가 순차적으로 실행됩니다.
35+
2. 소스코드 실행에 필요한 정보인 `변수``함수`의 참조를 실행 컨텍스트가 관리하는 스코프에서 검색합니다.
36+
- 변수 값의 변경 등 소스코드의 실행 결과는 다시 실행 컨텍스트가 관리하는 스코프에 등록합니다.
37+
38+
<br>
39+
40+
## 실행 컨텍스트의 역할
41+
> 전역 코드와 함수 코드로 예제를 살펴봅시다.
42+
43+
자바스크립트 엔진은 전역 코드 평가 - 실행, 함수 코드 평가 - 실행을 순차적으로 진행합니다.
44+
1. 전역 코드 평가
45+
- 전역에 존재하는 변수와 함수 선언문을 먼저 실행하여 실행 컨텍스트의 **전역 스코프**에 등록됩니다.
46+
- var 키워드로 선언한 변수와 함수 선언문의 경우 전역 객체의 프로퍼티가 됩니다.
47+
- let, const 키워드로 선언한 변수는 보이지 않는 개념적 블록에 존재합니다.
48+
49+
2. 전역 코드 실행
50+
- 런타임이 시작됩니다. 전역 변수에 값이 할당되고 함수가 호출됩니다.
51+
- 함수가 호출되면 전역 코드 실행이 일시 중단되고 함수 내부로 진입하여 코드를 실행합니다.
52+
53+
3. 함수 코드 평가
54+
- 함수의 매개변수와 지역 변수 선언문을 먼저 실행하고 실행 컨텍스트의 **지역 스코프**에 등록됩니다.
55+
- 함수 내부에서 지역 변수처럼 사용 가능한 **arguments 객체가 생성되어 지역 스코프에 등록**되고 **this 바인딩도 결정**됩니다.
56+
57+
4. 함수 코드 실행
58+
- 런타임이므로 매개변수와 지역 변수에 값이 할당됩니다.
59+
- 함수 호출 코드가 존재한다면 함수를 호출한 식별자를 스코프 체인을 통해 검색합니다.
60+
- 전역 스코프까지 탐색하나 전역 스코프에 해당 함수가 존재하지 않다면 전역 객체의 프로퍼티를 전역 스코프처럼 검색합니다.
61+
- 호출한 함수 메서드를 식별자 객체의 프로토타입 체인을 통해 검색합니다.
62+
- 인수가 존재한다면 인수를 전달한 표현식을 평가하고, 각 식별자를 스코프 체인을 통해 검색합니다.
63+
- 함수 실행이 종료되면 함수 호출 이전으로 돌아가 전역 코드 실행을 계속합니다.
64+
65+
이처럼 코드가 실행되려면 스코프를 구분해 식별자와 바인딩된 값이 관리되어야 하며, 중첩 관계에 의해 스코프 체인을 형성하고 식별자를 검색할 수 있어야 합니다. 또한 전역 객체의 프로퍼티도 전역 변수처럼 검색할 수 있어야 하죠.
66+
67+
함수 호출이 종료되면 함수 호출 이전으로 돌아가므로 `현재 실행 중인 코드``이전에 실행하던 코드`를 구분하여 관리해야 합니다. 즉 아래와 같은 조건이 생기죠.
68+
1. 선언에 의해 생성된 `모든 식별자(변수, 함수, 클래스 등)`를 스코프를 구분하여 등록하고 `상태 변화(식별자에 바인딩 된 값의 변화)를 지속적으로 관리`할 수 있어야 합니다.
69+
2. 스코프는 중첩 관계에 의해 `스코프 체인을 형성`해야 하며, 스코프 체인을 통해 상위 스코프로 이동하며 식별자를 검색할 수 있어야 합니다.
70+
3. 현재 실행 중인 코드의 실행 순서를 `변경(함수 호출에 의한 실행 순서 변경 등)`할 수 있어야 하며, `되돌아` 갈 수도 있어야 합니다.
71+
72+
이 모든 것을 관리하는 게 실행 컨텍스트로 소스코드를 실행하는데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역입니다. 즉, **식별자(변수, 함수, 클래스 등)를 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 메커니즘이며, 모든 코드는 실행 컨텍스트를 통해 실행됩니다**. 식별자와 스코프는 실행 컨텍스트의 **렉시컬 환경(Lexical Enviroment)** 으로 관리하고, 코드 실행 순서는 **실행 컨텍스트 스택**으로 관리합니다.
73+
74+
아래 코드로 실행 컨택스트 스택에 대해 자세히 알아봅시다.
75+
76+
<br>
77+
78+
## 실행 컨텍스트 스택
79+
> 자바스크립트 엔진은 실행 컨텍스트를 **스택(Stack) 자료구조**로 관리하며, 이를 실행 컨텍스트 스택이라고 합니다.
80+
81+
코드와 함께 시작합니다.
82+
83+
```js
84+
// 1. 전역 코드 : 전역 변수 선언
85+
const x = 1;
86+
const y = 2;
87+
88+
// 전역 코드 : 함수 정의
89+
function out(){
90+
// 2. 함수 코드 : 지역 변수 선언
91+
const x = 10;
92+
93+
function in(){
94+
const y = 20;
95+
console.log(x + y);
96+
}
97+
in();
98+
}
99+
100+
out();
101+
```
102+
103+
위 코드를 실행하면 순차적으로 실행 컨텍스트 스택가 추가(push)되거나 제거(pop)됩니다. 도식화하면 아래와 같아요.
104+
105+
<br>
106+
107+
<div align='center'>
108+
109+
<img src='./img/execution_context/execution_context_stack.jpg' width='600'/>
110+
111+
<br>
112+
113+
<div align="left">
114+
<ul style="list-style:none;">
115+
<li>
116+
1. 전역 변수 x와 y, 함수 out은 전역 실행 컨텍스트에 등록(push)되고, 런타임이 시작되면 전역 변수에 값이 할당되고 out이 호출됩니다.
117+
</li>
118+
<br>
119+
<li>
120+
2. 함수 out이 호출되어 코드 제어권(Control)이 out 함수 내부로 이동한 뒤 out 함수 내부의 함수 코드를 평가하여 out 함수 실행 컨텍스트를 생성하고 스택에 추가(push)합니다. 이 때 지역 변수 x와 내부 함수 in이 out 함수 실행 컨텍스트에 등록되고, 런타임이므로 지역 변수에 값이 할당되고 내부 함수 in이 호출됩니다.
121+
</li>
122+
<br>
123+
<li>
124+
3. 함수 in이 호출되어 코드 제어권이 in 함수 내부로 이동한 뒤, in 함수 내부의 함수 코드를 평가하여 in 함수 실행 컨텍스트를 생성하고 스택에 추가(push)합니다. 이 때 지역 변수 y가 in 함수 실행 컨텍스트에 등록되고, 런타임이므로 y에 값을 할당한 뒤 console.log 메서드를 호출하고 종료됩니다.
125+
</li>
126+
<br>
127+
<li>
128+
1. in 함수가 종료되었으므로 코드 제어권이 다시 out 함수로 이동합니다. in 함수가 종료되었으므로 스택에서 제거(pop)됩니다. 그리고 in 함수는 더 이상 실행할 코드가 없으므로 종료됩니다.
129+
</li>
130+
<br>
131+
<li>
132+
1. foo 함수가 종료되었으므로 코드 제어권은 다시 전역 코드로 이동합니다. out 함수가 종료되었으므로 스택에서 제거(pop)됩니다. 그리고 전역 코드는 더 이상 실행할 코드가 없으므로 종료되며 실행 컨텍스트에서 제거(pop)됩니다.
133+
</li>
134+
</ul>
135+
</div>
136+
137+
</div>
138+
139+
<br>
140+
141+
이처럼 실행 컨텍스트 스택은 코드의 실행 순서를 관리하죠. 소스코드가 평가되면 실행 컨텍스트가 생성되고 실행 컨텍스트 스택의 최상위에 쌓입니다. 즉, **실행 컨텍스트 스택의 최상위에 존재하는 실행 컨텍스트는 언제나 현재 실행 중인 코드의 실행 컨텍스트**입니다. 이를 실행 중인 `실행 컨텍스트(Running Execution Context)`라고 합니다.
142+
143+
<br>
144+
145+
## 렉시컬 환경(Lexical Enviroment)
146+
> 식별자와 식별자에 바인딩 된 값, 상위 스코프에 대한 참조를 기록하는 자료구조로 실행 컨텍스트를 구성하는 컴포넌트입니다.
147+
148+
`실행 컨텍스트 스택`**코드의 실행 순서를 관리**한다면 `렉시컬 환경`**스코프와 식별자를 관리**합니다.

0 commit comments

Comments
 (0)