JavaScript 런타임은 크게 세 영역으로 구분된다.
1. 엔진
2. 웹 API
3. 이벤트 큐
이는 JavaScript의 브라우저 런타임에 해당하고 Node JS의 런타임과는 다르니 주의하자. (Node JS의 런타임에는 Web API 대신 C++ 바인딩과 스레드 풀이 존재한다)
첫번째, JavaScript 엔진은 크게 두 영역으로 나뉜다.
1. 콜 스택: 작성한 코드가 실행되는 영역. (아래서 더 디테일하게 다룰 예정)
2. 힙: 비구조화된 메모리 영역으로 원시형을 제외한 모든 참조형 객체에 대한 메모리 할당이 이루어지는 영역.
두번째, 웹 API는 JavaScript 엔진의 일부가 아니지만 웹 프로그래밍을 할 때 많이 사용되는 API로써 대표적인 예로는 DOM, timer 함수, fetch 함수 등이 있다. (상세 내용을 MDN 문서 참고: developer.mozilla.org/en-US/docs/Web/API)
마지막으로 모든 콜백 함수를 담고있는 자료구조인 이벤트 큐가 있다.
예를 들어 특정 버튼에 클릭 이벤트를 연결할 때, 해당 버튼이 클릭되고 가장 먼저 버튼 클릭 이벤트의 콜백 함수가 이벤트 큐에 담긴다. 이벤트 큐는 이 예시를 포함한 다른 콜백 함수들을 담고 있으며 콜 스텍이 비워지면 이벤트 루프를 통해 이벤트 큐에 담긴 콜백 함수가 하나하나 콜 스텍에 전달되어 콜백 함수가 실행된다.
JavaScrip 런타임의 세 영역을 다음의 그림으로 이해하면 된다.
위 그림의 JS 엔진 영역의 콜 스택 안에 쌓여있는 실행 컨텍스트(EC: execution context)를 좀 더 살펴보자.
개별 함수마다 생성되는 실행 컨텍스트는 해당 함수가 잘 실행되기 위해 필요한 모든 정보들을 담고 있다.
개별 함수의 실행 컨텍스트가 담고 있는 정보는 다음과 같다.
1. 변수 영역
- let, const, var 키워드로 생성한 모든 변수
- 함수
- 함수에 전달받은 인자
2. 스코프 체인
- 현재 함수의 부모 함수들이 가진 변수들에 대한 참조
3. this 키워드
실제 코드를 통해 앞서 배운 내용을 살펴보자
왼쪽 코드와 오른쪽 콜 스텍을 비교해가며 살펴보자. 일단 콜 스텍의 가장 아래에 위치한 전역 실행 컨텍스트가 있다. 이 전역 실행 컨텍스트는 프로그램의 크기와 상관없이 프로그램 별 단 하나만 존재한다. 전역 컨텍스트에는 전역에 선언된 모든 변수들이 포함된다. (a, first(), second(), x) 코드의 마지막 줄에 이르러 first() 함수가 마침내 호출될 때 콜 스텍에 어떤 변화가 일어나는지 보자.
first() 함수의 실행 컨텍스트가 콜 스텍에 추가된다. 이때 각 함수의 실행 컨텍스트의 변수 영역에 포함된 변수들도 실행 컨텍스트에 표기하였다. first() 함수의 두번째 라인에 다다르면 second() 함수가 호출된다. 이와 동시에 역시 second() 함수의 실행 컨텍스트도 콜 스텍에 쌓이게 된다.
second() 함수에는 함수 내에서 선언된 d 변수를 포함한 인자로 받은 값 (3과 6)이 각 num1과 num2 변수에 할당되어 second() 함수의 변수 영역의 일부에 존재하는 것을 알 수 있다. 그리고 second() 함수와 first() 함수의 실행이 끝나면 각 함수의 실행 컨텍스트가 콜 스텍에서 사라져 다시 콜 스텍이 처음 상태로 돌아온다.
각 함수 별 실행 컨텍스트는 함수 생성과 동시에 만들어지나 실제 콜 스택에 추가되는 것을 각 함수가 실행될 때 임을 주의하자.
이렇게 JavaScript 런타임 구조에서 부터 코드를 따라 읽으며 JS 엔진 내부의 콜 스텍이 어떻게 변하는지까지 살펴보았다.
'JAVASCRIPT' 카테고리의 다른 글
비동기 프로그래밍 (0) | 2020.11.28 |
---|---|
생성자 함수와 Prototype (0) | 2020.11.17 |
Closure의 이해 (0) | 2020.11.17 |
this 키워드 (0) | 2020.11.16 |
Hoisting과 Temporal Dead Zone (TDZ) (0) | 2020.11.16 |