자바스크립트 엔진
자바스크립트를 실행하기 위해서는 자바스크립트 엔진이 필요하다. 자바스크립트 엔진은 자바스크립트 코드를 실행하는 프로그램 또는 인터프리터이다.
인터프리터란?
프로그래밍 언어의 소스 코드를 바로 실행하는 컴퓨터 프로그램 또는 환경을 말한다.
원시 코드를 기계어로 번역하는 컴파일러와 대비된다.
자바스크립트 엔진의 대표적인 예시로는 구글의 V8 엔진이 있다.
자바스크립트 엔진의 주요 구성요소로는 메모리 힙(Memory Heap)과 콜 스택(Call stack)이 있다.
- 메모리 힙(Memory Heap) : 메모리 할당이 일어나는 곳
- 콜 스택(Call Stack) : 코드가 실행될 때 호출 스택이 쌓이는 곳
[ 메모리 힙 ]
변수 선언, 함수 저장, 호출 등의 작업이 발생하는 공간
const num = 531; 라는 코드는 num 이라는 변수를 위해 메모리 공간을 할당하고 그 공간에 531이라는 값을 할당하는 것이다.
이와 같은 동작이 일어나는 공간이 바로 메모리 힙이다.
[ 콜 스택 ]
코드를 읽어내려가면서 수행할 작업들을 밑에서부터 하나씩 쌓고 메모리 힙에서 작업 수행에 필요한 것들을 찾아서 작업을 수행하는 공간
즉, 콜 스택이란 기본적으로 우리가 프로그램 상에서 어디에 있는지를 기록하는 자료구조를 말한다.
만약 우리가 특정 함수를 실행하게 되면 해당 함수는 콜 스택의 가장 상단에 위치하게 된다. 그리고 함수 실행이 끝나게 되면, 해당 함수는 콜 스택에서 제거되게 된다.
자바스크립트는 기본적으로 싱글 스레드(Single Thread) 기반 언어이기 때문에, 호출 스택이 하나이다. 따라서 한 번에 하나의 작업만 처리할 수 있다.
function multiply(x, y) {
return x * y;
}
function printSquare(x) {
var s = multiply(x, x);
console.log(s);
}
printSquare(5);
처음 엔진이 위의 코드를 실행하는 시점에는, 콜 스택은 비어있는 상태이다. 하지만 코드가 실행되면서 콜 스택은 아래와 같이 변하게 된다.
콜 스택의 각 단계를 스택 프레임(Stack Frame)이라고 한다.
만약 스택을 초과하게 된다면 어떻게 될까? 무한 루프를 도는 코드를 돌리면 Maximum call stack size 에러가 발생하게 된다.
function foo() {
foo();
}
foo();
콜 스택은 정해진 스택 사이즈가 존재하고, 하나씩 쌓이기 때문에 정해진 용량을 초과하게 되면 에러가 발생하게 된다. 흔히들 이것을 Stack Overflow라고 말한다. 유명한 개발자 포럼 사이트의 이름도 이것에서 따온 것이다.
런타임
자바스크립트 엔진은 싱글 스레드 기반 언어이기 때문에, 다른 작업을 수행하려면 현재 수행중인 작업이 끝날때까지 기다려야 하는 문제점이 있었다. 또한, 많은 시간이 걸리는 작업을 수행하게 된다면 프로그램이 엄청나게 느려질 우려 역시 존재했다.
그렇기 때문에, 오랜 시간이 걸리는 작업들은 백그라운드에서 처리하고 간단하게 처리할 수 있는 작업들만 콜 스택에서 처리한다면 효율적으로 처리가 가능하였다. 이러한 과정들이 가능하게 해준 것이 바로 자바스크립트 런타임이다.
[ Web API ]
Ajax 요청, setTimeout(), 이벤트 핸들러의 등록과 같이 웹 브라우저에서 제공하는 기능
개발자 도구에서 콘솔창에 window를 입력해보자.
엄청나게 방대한 양의 Web API가 존재함을 확인할 수 있다. 이러한 Web API들을 사용하여 백그라운드에서 비동기적으로 작업을 처리할 수 있고 , 이러한 작업이 끝나면 콜 스택에게 해당 작업이 끝났음을 알려주어 계속해서 작업을 수행해 나갈 수 있게 된다.
[ 콜백 큐(Callback Queue) ]
setTimeout이나 setInterval과 같은 비동기 함수의 콜백 함수 또는 이벤트 핸들러가 일시적으로 보관되는 영역이다.
[ 이벤트 루프(Event Loop) ]
이벤트 루프는 콜 스택에 현재 실행 중인 실행 컨텍스트가 있는지, 그리고 콜백 큐에 대기 중인 함수(콜백 함수, 이벤트 핸들러 등)가 있는지 반복해서 확인한다. 만약 콜 스택이 비어 있고 태스크 큐에 대기 중인 함수가 있다면 이벤트 루프는 순차적(FIFO, First In First Out)으로 콜백 큐에 대기 중인 함수를 콜 스택으로 이동시킨다. 이때 콜 스택으로 이동한 함수는 실행된다.
정리
- Memory Heap: 메모리 할당이 이루어지는 곳
- Call Stack: 코드가 실행될 때 호출 스택이 쌓이는 곳
- Web APIs: 콜스택에서 실행된 비동기 함수는 Web API를 호출하고 Web API는 콜백 함수를 콜백 큐에 넣음
- Callback Queue: 함수를 저장하는 자료구조로 선입선출 형식으로 함수를 처리
- Event Loop: 콜스택이 다 비워지면 콜백 큐에 있는 함수들을 하나씩 콜스택에 옮김