자바스크립트의 특징

자바스크립트는 싱글 스레드 기반의 언어입니다. 여기서 스레드란 작은 단위의 실행 흐름을 말합니다. 자바스크립트 엔진을 간단히 살펴보면 위와 같이 Memory Heap과 Call Stack(자료구조에서 배우게 될 stack처럼 구현된 저장소)으로 구성되어 있는데요. 하나의 스레드에서 하나의 Call Stack으로 현재 어떤 함수가 동작하고 있는지, 그 함수 내에서 어떤 함수가 동작하고, 다음에 어떤 함수가 호출되어야 하는지 등을 제어합니다.
런타임 (브라우저 또는 Node.js)환경
위에서 확인한 것처럼 자바스크립트 엔진은 단일 Call Stack으로 요청이 들어온 순서대로 한 가지 일만을 수행합니다. 그러면 setTimeout 과 같이 타이머가 완료된 뒤 callback 함수를 실행하는 비동기 함수는 어떻게 실행할까요? 비동기 요청은 자바스크립트 엔진을 구동하는 런타임 환경에서 담당합니다.

브라우저의 경우 setTimeout 을 예로 들면, Call Stack에서 Web API setTimeout 요청 이후 제거됩니다. Web API에서 setTimeout 이 완료되면 setTimeout callback 함수를 Callback Queue(자료구조에서 배우게 될 queue처럼 구현된 저장소, 세분화된 queue들이 있음)로 옮깁니다. 현재 실행한 자바스크립트 코드를 모두 실행한 뒤, Event Loop가 지속적으로 Call Stack이 비어있는지 확인하고, 비어있다면 Callback Queue에 있는 작업 순서대로 Call Stack으로 넘겨 실행하도록 만듭니다.
예시 코드
// 1번
let num = 1;
// 2번
setTimeout(() => {
num = 2;
}, 0);
// 3번
num = 3;
// 4번
console.log(num);
예시 코드의 실행
- 1번 실행으로 num 에 1이 할당됩니다.
- 2번 실행으로 setTimeout 을 Web API(NodeJS의 경우 Timers 모듈)가 처리하도록 넘깁니다. 이때 중요한 건, 즉시 setTimeout 에 있는 callback을 실행할지 판단하지 않습니다. 따라서 num 은 여전히 1인 상태입니다.
- 한편, Web API에서는 setTimeout 작업이 완료되면 setTimeout callback 함수를 Callback Queue에 등록합니다.
- 3번 실행으로 num 에 3이 재할당됩니다.
- 4번 실행으로 화면에 3이 출력됩니다.
- 이렇게 모든 실행을 마치면, 그 후에 Event Loop를 돌아 Callback Queue에 있는 callback 함수를 Call Stack으로 가져와 실행하고 num 은 2가 재할당됩니다.
참고자료
- 코드잇 제공자료