자바스크립트의 가장 큰 특징 중 하나는 단일 스레드(Single thread)
기반 언어이며, 동기적
언어 이다. 이 의미는 동시에 하나의 작업만을 처리할 수 있다라는 말이다. 하지만 실제로 자바스크립트가 사용되는 환경을 생각해보면 많은 작업이 동시에 처리되고 있는 걸 볼 수 있다. 어떻게 동시에 처리할 수 있는 걸까...
이때 등장하는 개념이 이벤트 루프(event loop)
이다.
자바스크립트 엔진은 Memory Heap 과 Call Stack 으로 구성되어 있다.
가장 유명한 것이 구글의 V8 Engine이다.
자바스크립트는 단일 스레드 (sigle thread) 프로그래밍 언어인데,
이 의미는 Call Stack이 하나 라는 의미이다.
엔진(v8) 요청이 들어올 때마다 해당 요청을 순차적으로 호출 스택에 담아 처리할 뿐이다.
그렇다면 비동기 요청은 어떻게 이루어지며, 동시성에 대한 처리는 누가 하는 걸까?
바로 이 자바스크립트 엔진을 구동하는 환경, 즉 브라우저나 Node.js가 담당한다.
Web API 는 브라우저에서 제공하는 API 로, DOM, Ajax, Timeout 등이 있다.
Call Stack에서 실행된 비동기 함수는 Web API를 호출하고,
Web API는 콜백함수를 Callback Queue에 담아둔다.(promise, callback, clickevent etc..)
비동기적으로 실행된 콜백함수가 보관 되는 영역.
Task Queue, Microtask Queue 등이 존재 한다.(setTimeout, promise 등 다른 큐에 추가된다)
Event Loop는 Call Stack과 Callback Queue의 상태를 체크하여,
Call Stack이 빈 상태가 되면, Callback Queue의 첫번째 콜백을 Call Stack에 추가한다.
다음 코드를 바탕으로 자바스크립트 처리과정을 살펴보자.
console.log("script start");
setTimeout(function() {
console.log("setTimeout");
}, 0);
Promise.resolve().then(function() {
console.log("promise1");
}).then(function() {
console.log("promise2");
});
console.log("script end");
위의 코드를 실행하면 다음과 같은 결과 화면을 얻을 수 있다.
script start
script end
promise1
promise2
setTimeout
Promise, setTimeout 순으로 실행되는 이유 = Microtask
마이크로 태스크는 쉽게 말해 일반 태스크보다 더 높은 우선순위를 갖는 태스크라고 할 수 있다. 즉, 태스크 큐에 대기중인 태스크가 있더라도 마이크로 태스크가 먼저 실행된다.
즉, Promise의 then()의 콜백 은 Task Queue가 아닌 Microtask Queue에 담긴다.