
JavaScript(자바스크립트): 웹페이지에 동적인 기능을 담당하는 스크립트 프로그래밍 언어
Runtime(런타임): 코드가 실행되는 환경
→ JavaScript는 브라우저, Node.js 등의 런타임을 가짐
JavaScript Engine(자바스크립트 엔진): 자바스크립트 코드를 해석하고 실행하는 프로그램 또는 인터프리터
JavaScript는 런타임과 엔진 이 두 가지가 함께 동작하며 구동된다!
JavaScript는 하나의 Call Stack을 가지는 Single Thread
자바스크립트는 단일 스레드 (=한번에 하나의 작업만 실행)
따라서, 멀티스레드 기반의 비동기 처리를 도와주는 런타임 환경이 필요하다
즉, 자바스크립트 엔진이 싱글스레드로 동작하고, 런타임 환경이 멀티스레드를 지원한다고 보면 된다

Memory Heap
동적으로 할당된 메모리를 저장하는 곳
객체, 배열, 함수와 같은 데이터 구조가 메모리 힙에 저장
Call Stack
현재 실행하고 있는 함수의 실행 컨텍스트를 추적하는 자료구조 → Stack(LIFO)
함수 호출이 순차적으로 실행된다
위 런타임 환경 구조 설명에서 비동기 처리를 도와주는 요소를 더 자세히 파고 들어가보면
런타임 환경의 Call Stack, Web API, Task Queue, Event Loop 가 유기적으로 상호작용하여 비동기 작업을 병렬적으로 처리함으로써 멀티 스레드처럼 동작하도록 해준다

Web API
브라우저 환경에서 시간이 소요되는 작업을 처리
→ setTimeout, DOM Event, 비동기 요청 등
Task Queue
비동기 처리된 콜백 함수가 대기하는 Queue (FIFO)
비동기 콜백이 대기하는 공간이라는 의미로 Callback Queue라 부르기도 한다
서로 다른 우선순위를 가진 두 개의 큐로 구성
Task Queue (Macrotask Queue)
Macrotask Queue도 원래 Task Queue로 불리다 Microtask Queue 개념이 추가되면서 구분을 위해 붙여짐
setTimeout, setInterval, addEventListener 등의 콜백이 들어감
Microtask Queue
Promise, process.nextTick, MutationObserver 등의 콜백이 들어감
Microtask Queue 가 우선적으로 실행
→ 이벤트 루프는 Microtask Queue가 완전히 빌 때까지 Macro Queue 로 넘어가지 않음
Event Loop
Call Stack 과 Task Queue를 지속적으로 모니터링하는 관리자
Task(작업)가 들어오길 기다렸다가
Task가 들어오면 이를 처리하고,
처리할 Task가 없는 경우엔 잠드는,
끊임없이 돌아가는 자바스크립트 내 루프
Call Stack이 비어있는지 확인 후 비어 있다면 Task 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');

console.log('script start') 가 Call Stack에서 실행 후 제거setTimeout() 이 Call Stack에서 들어오고 Web API에 위임Promise.resolve()가 즉시 이행되면서 .then(fn1) 의 콜백이 Microtask Queue에 등록console.log('script end') 가 Call Stack에서 실행 후 제거.then(fn2) 의 콜백(fn2)이 Microtask Queue에 등록자바스크립트는 싱글 스레드 기반 언어인데 비동기 프로그래밍은 왜 가능한 걸까요?
자바스크립트는 엔진과 런타임이 함께 구동되어 실행되는데요.
자바스크립트 엔진 자체는 싱글 스레드로 동작하지만, 브라우저나 Node.js 같은 런타임 환경이 멀티스레드를 지원하기 때문입니다.
모든 작업은 자바스크립트 엔진의 Call Stack 에서 순차적으로 실행되지만, 시간이 오래 걸리는 비동기 작업은 자바스크립트 엔진이 직접 처리하지 않고 Web API로 위임합니다.
Web API는 브라우저 내부 스레드에 작업을 위임한 뒤 처리하고, 해당 콜백을 Task Queue에 넣어 대기시킵니다. 이후 Event Loop가 Call Stack이 비어있는 것을 확인하면 Task Queue에서 콜백을 꺼내 Call Stack으로 올려 실행합니다.
이 구조 덕분에 자바스크립트는 싱글 스레드임에도 비동기 프로그래밍이 가능한 것입니다.
마이크로태스크 큐와 태스크 큐에 대해서 말씀해주세요.
두 큐 모두 비동기 콜백이 대기하는 공간이지만 우선순위가 다릅니다. Event Loop는 Call Stack이 비워지면 Microtask Queue를 먼저 확인하고, 해당 큐가 완전히 빌 때까지 모두 처리한 뒤에 Task Queue로 넘어갑니다. 대표적으로 Promise 콜백은 Microtask Queue에, setTimeout 콜백은 Task Queue(Macrotask Queue) 에 들어갑니다.
자바스크립트 엔진: "어, 아직 싱글이야" | JS 런타임에 대해 알아보자
마이크로태스크 큐, 태스크 큐
🔄 자바스크립트 이벤트 루프 동작 구조 & 원리 끝판왕
Micro Task vs Macro Task
자바스크립트 런타임을 이해해보자