JavaScript는 싱글 스레드로 동작한다. 싱글 스레드로 동작한다는 것은 stack이 하나밖에 없다는 뜻이고, 이럴 경우 동시에 하나의 작업만 처리할 수 있다. 브라우저에서 동작하는 JavaScript의 특성 상 한 번에 하나의 작업만 처리할 수 있다면 작업 속도가 늦어 브라우저 사용 시 UX가 좋지 않을 수 밖에 없다. 그렇기에 동기적으로 작업을 처리하는 stack에 더하여 비동기적으로 작업을 처리하는 것이 매우 중요하다.
JavaScript의 비동기 작업에는 Ajax 통신
, Promise
와 async/await
비동기 처리, 이벤트 처리, setTimeout
과 setInterval
등의 DOM API, 1초에 60번 애니메이션 처리를 요청하는 requestAnimationFrame
등이 있다. 이러한 비동기 작업들은 모두 Web API
가 담당한다. JavaScript의 Call stack
에서 비동기 작업이 요청되면 Web API
에 비동기 작업 처리를 요청하게 되는 것이다. Web API
에서 처리가 완료된 작업은 요청의 종류에 따라 각각 Task Queue
, Microtask Queue
, Animation Frames
에 등록된 후 Event Loop
에 의해 Call stack
에 등록된다.
Web API
에서 처리 완료된 작업들이 Queue에 할당되었다고 해서 Event Loop
가 비동기 작업들을 바로바로 Call stack
에 등록하지는 않는다. Call stack
에 이러한 작업들을 등록하기 위해서는 필수적으로 Call stack
이 비어져있는 상태여야만 한다. 즉, JavaScript 싱글 스레드의 stack
에 등록되어진 모든 동기적 작업들이 마무리 되어야만 완료된 비동기 작업들이 Call stack
에 등록될 수 있는 것이다.
이러한 방식대로 작업을 처리하기 위해 Event Loop
는 주기적으로 Call stack
과 각 Queue의 상태를 확인한다. 만약 Call stack
이 비어있다면 제일 먼저 Microtask Queue
에 있는 작업을, 다음으로는 Animation Frames
, 그리고 마지막으로는 Task Queue
에 있는 작업을 Call stack
에 등록한다.
Microtask Queue
에는 Promise
, async/await
, process.nextTick()
, Object.observe()
, MutationObserver()
등의 메소드가 등록된다. 해당 작업들은 Call stack
이 비워지면 Event Loop
에 의해 가장 먼저 등록된다.
requestAnimationFrame()
등의 브라우저 렌더링 관련 작업들이 등록된다. 이 작업들은 Call stack
이 비워지고 Microtask Queue
도 비워진 후 Call stack
에 등록된다.
setTimeout()
, setInterval()
등의 DOM API가 등록된다. Microtask Queue
와 구분짓기 위해 Macrotask Queue
라고 불리는 경우도 있으며, 가장 마지막에 Call stack
에 등록된다.
JavaScript의 비동기 작업들은 Web API
에 의해 처리되며, Event Loop
에 의해 Call stack
이 비워지면 다시 등록된다. 이 때, Call stack
에 등록되는 Queue의 순서는 Microtask Queue
-> Animation Frames
-> Task Queue
이다.
자바스크립트 비동기 처리 과정과 RxJS Scheduler
[JavaScript] Task Queue말고 다른 큐가 더 있다고? (MicroTask Queue, Animation Frames)