TL;DR
- 자바스크립트는 싱글 쓰레드이지만, 브라우저가 멀티 쓰레드이므로 비동기 처리가 가능하다.
- 이벤트 루프 시스템은 자바스크립트 엔진이 아닌 브라우저에 있다.
자바스크립트는 싱글 스레드(single thread)로 동작한다. 왜냐하면 콜 스택(call stack)이 하나만 존재하기 때문이다. 그렇다면 브라우저에서 실행되는 스크립트는 어떻게 비동기적으로 데이터를 불러오고 애니메이션을 실행시킬까? 어떤 원리로 애니메이션과 클릭 이벤트를 같이 처리할 수 있을까? 그 이유는 브라우저에 이벤트 루프 시스템이 있기 때문이다.
브라우저에서 스크립트가 실행되는 동작을 살펴보려면 네 가지 요소를 알아야 한다. 1) 자바스크립트 엔진
, 2) 브라우저가 제공하는 웹 API
(Web APIs), 3) 태스크 큐
(Task Queue), 4) 이벤트 루프 시스템
(Event loop system)이 있다.
이미지 출처: medium - Asynchronous Javascript (Event Loop)
아래 스크립트를 브라우저에서 실행할 때 내부적으로 어떤 일이 일어날까?
function hello() {
setTimeout(function cb1() {
console.log("Hi, cb1 is done");
}, 1000);
}
function bye() {
setTimeout(function cb2() {
console.log("Bye, cb2 is done");
}, 1000);
}
hello();
by();
자바스크립트 엔진
에 의해 자바스크립트 코드가 실행되면 자바스크립트 콜 스택에 코드가 차례대로 쌓인다.
setTimeout
처럼 웹 API
를 불러오는 코드가 실행되면 setTimeout
코드는 콜 스택에 쌓였다가 실행이 완료되면 콜 스택에서 빠지고 setTimeout
비동기 작업이 끝나면 해당 콜백 cb1
이 태스크 큐
로 이동한다. setTimeout
코드가 실행되면 마찬가지로 콜 스택에 쌓였다가 실행이 완료되면 콜 스택에서 빠지고 setTimeout
비동기 작업이 끝나면 해당 콜백 cb2
가 태스크 큐
로 이동한다. 이벤트 루프 시스템
에 의해 태스크 큐
에 있던 cb1
이 콜 스택으로 푸시(push) 된다. 이렇게 태스크 큐
에 있다가 콜 스택으로 하나씩 쌓이는 것을 틱(tick)이라고 한다. cb1
의 실행이 모두 완료되어 콜 스택이 비어 있으면 cb2
도 그제서야 콜 스택에 쌓인다.결론적으로 브라우저 또는 Node.js는 멀티 쓰레드로 작동하기 때문에 비동기 데이터 불러오기나 애니메이션과 클릭 이벤트 처리를 동시에 할 수 있는 것이다.