자바스크립트 엔진은 Memory Heap과 Call Stack을 제공한다.
여기서 자바스크립트 엔진은 자바스크립트 코드를 컴퓨터가 이해할 수 있도록 해석하고 실행하는 interpreter이다.
Stack
인 만큼 LIFO(Last In First Out)의 특성을 갖는다. function foo() {
foo();
}
foo();
여기까지만 보면 자바스크립트는 하나의 Call Stack을 가지고, 그 Call Stack에 함수들이 쌓여 위에서부터 차례로 실행되므로 동기적으로 동작하는 것으로 보인다.
다음 첫번째 예시코드를 살펴보자.
const response = ajax('https://example.com/api');
console.log(response); //undefined
실행결과 콘솔에 undefined
가 찍히는 것을 알 수 있다. 동기적으로 동작한다면, ajax 요청이 끝날때까지 console.log(response)는 실행되지 않아야한다.
그런데 왜 ajax 요청이 끝나기 전에 response가 찍힌걸까?🤔
두번째 예시코드를 살펴보자.
function first() {
console.log('first');
}
function second() {
console.log('second');
}
function third() {
console.log('third');
}
first();
setTimeout(second, 1000);
third();
//first
//third
//second
여기서도 setTimeout 함수가 끝나기 전에 third 함수가 먼저 실행된 것을 확인할 수 있다.
자바스크립트 런타임의 공통점: 이벤트루프
자바스크립트가 실행되는 환경(런타임)인 브라우저에서는 Web API(DOM, AJAX, Timeout 등
)와 이벤트 루프, Callback Queue를 제공한다. 이 기능들이 자바스크립트로 하여금 비동기적으로 동작할 수 있도록 한다.
다시말해, 자바스크립트는 싱글스레드로 동기적으로 동작하지만, 자바스크립트가 실행되는 웹 브라우저에서 제공하는 이벤트루프 등으로 비동기적으로 동작할 수 있는 것이다.
자바스크립트 엔진은 혼자서 동작하지 않고, 웹브라우저, Node.js 등의 환경 내에서 실행된다. (이제는 더이상 이 두개의 환경에만 국한되지않고 모든 종류에 임베드되어 사용된다.) 이러한 환경들의 공통점은 모두 내장된 이벤트 루프라는 메카니즘이 있다는 것이다.
위의 이미지를 하나씩 살펴보도록 하자.
먼저 Web API란, 브라우저의 일부분으로 직접 접근할 수 없지만 API로 실행시킬 수 있는 스레드를 의미한다. 자바스크립트 실행환경이 Node.js라면, Web API가 아니라, C++ API가 될 것이다. (Node.js는 Javascript와 C++언어로 만들어졌기 때문)
Web API가 실행되었다면, 콜백함수는 Callback Queue에 푸시되고, Call Stack이 빌때까지 대기한다.
이벤트 루프의 역할은 Call Stack과 Callback Queue를 모니터하는 것이다. Call Stack이 비었다면, Callback Queue에서 첫번째 이벤트를 가져와 Call Stack에 푸시할 것이다.
다시 위의 예시로 돌아가 생각해보자.
function first() {
console.log('first');
}
function second() {
console.log('second');
}
function third() {
console.log('third');
}
first();
setTimeout(second, 1000);
third();
setTimeout 함수가 third 함수보다 먼저 실행되었지만, third 함수의 콘솔이 먼저 찍힌 이유는, setTimeout가 타이머를 생성하는 Web Api이므로 실행되기까지 시간이 걸려 Call Stack에서 빠져나와 Callback Queue에서 대기하고 있었기 때문이다.
reference
- https://www.youtube.com/watch?v=zphcsoSJMvM
- https://medium.com/weekly-webtips/multi-threading-in-nodejs-2605bcedc662
- https://developer.mozilla.org/ko/docs/Learn/JavaScript/Asynchronous/Introducing
- https://www.youtube.com/watch?v=zi-IG6VHBh8
- https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with-2f077c4438b5