자바스크립트는 싱글 스레드 언어인데, 어떻게 동시에 여러 작업들을 수행하나요?

프론트엔드와 관련된 질문이에요.

자바스크립트는 싱글 스레드 언어입니다. 즉, 한 번에 하나의 작업만을 처리할 수 있는 단일 콜 스택을 가집니다. 하지만 브라우저나 Node.js 환경이 제공하는 비동기 처리 메커니즘 덕분에 여러 작업을 동시에 수행할 수 있습니다.

자바스크립트는 브라우저의 Web API나 Node의 libuv, 이벤트 루프, 태스크 큐를 이용하여 비동기 작업을 동시에 처리합니다.

비동기 작업이 발생하면, 해당 작업(타이머, 네트워크 요청 등)은 브라우저의 Web API에 위임됩니다. 예를 들어, setTimeout이나 fetch와 같은 작업이 수행되면 자바스크립트 엔진은 이 작업들을 Web API에 넘기고 다른 코드 실행을 이어갑니다. Web API에서 비동기 작업이 완료되면, 그 작업은 태스크 큐에 들어가 대기합니다.

이후 이벤트 루프가 콜 스택이 비어있는지 확인한 뒤 태스크 큐에서 대기 중인 작업을 콜 스택으로 가져와 실행합니다. 이러한 구조 덕분에 자바스크립트는 싱글 스레드임에도 비동기적으로 작업을 처리하여 다양한 작업을 효율적으로 관리할 수 있습니다. 이 메커니즘 덕분에 UI 인터랙션이 끊기지 않으며, 대기 시간이 필요한 작업도 동시에 실행되는 것과 같이 동작하게 됩니다.

앞서 말씀하신 태스크 큐의 종류에는 어떤 게 있나요? 🤔

자바스크립트의 태스크 큐는 크게 매크로태스크 큐마이크로태스크 큐로 나뉩니다. 이들 큐는 비동기 작업의 우선순위를 관리하고, 이벤트 루프가 적절한 시점에 콜백을 실행하기 위해 사용됩니다.

첫째, 매크로태스크 큐는 일반적인 비동기 작업의 콜백이 저장되는 큐입니다.
setTimeout, setInterval, I/O 작업, 이벤트 핸들러 등은 작업 완료 후 매크로태스크 큐에 콜백을 대기시킵니다. 매크로태스크 큐는 이벤트 루프의 한 번의 반복마다 하나의 태스크만 처리되므로, UI 업데이트나 다른 작업과 균형 있게 진행됩니다.

둘째, 마이크로태스크 큐는 더 높은 우선순위가 필요한 비동기 작업들이 대기하는 큐입니다.
Promise.then, MutationObserver 등의 비동기 콜백이 여기에 저장됩니다. 이벤트 루프는 매크로태스크를 실행하기 전에 항상 마이크로태스크 큐를 먼저 확인하고, 모든 마이크로태스크를 처리한 후 매크로태스크로 넘어갑니다. 이 방식으로 마이크로태스크 큐의 작업은 높은 우선순위로 처리됩니다.

📚 추가 학습 자료를 공유합니다.