궁금했던 이유
JS는 기본적으로 싱글 스레드로 작동한다. 근데 비동기 처리를 한다. 오히려 더 헷갈렸다.
아니..싱글 스레드인데 어떻게 비동기처리하는 거지? 왜냐하면 싱글 스레드가 여러 일을 분담해서 할 수 없다고 생각했기 때문이다.
비동기를 처음 설명할 때 가장 쉬운 예시이다. setTimeout()은 비동기 함수이다.
// 스레드 출발!
console.log("1");
setTimeout(() => { // <- 이 녀석은 대체 어디서 처리가 되서 오는거지?
console.log("2");
});
console.log("3");
결과
1
3
2
위 코드에서 내가 궁금했던 것은 setTimeout() 함수가 비동기라면 기존 흐름에서 벗어나 어딘가 에서 동작해야되는거 아닌가? 라는 생각이 들었고, 더 나아가 어딘가 가 무엇인지 궁금해졌다.
결론적으로 말하자면 자바스크립트는 싱글 스레드가 맞지만, 자바스크립트를 구동하는 런타임 환경(Node, 브라우저)는 멀티 스레드 환경이기 때문이다. 멀티 스레드 환경을 이벤트 루프라고 부른다.
브라우저 구성
해당 영역들이 어떤 역할과 특징을 간략하게 살펴보도록 하자.

| 명칭 | 특징 및 설명 |
| Memory Heap | 자바스크립트 객체 저장 공간 |
| Call Stack | 코드를 실행하기 위한 메모리 구조 (LIFO 구조) 이용한 함수는 Call Stack에서 지워진다. |
| Web APIs | 브라우저에서 제공하는 API 모음 (쉽게 비동기 실행들은 여기로 보내진다고 생각하면 된다) |
| Task Queue | Web APIs에서 작업 끝난 함수들이 대기하는 공간 Task Queue는 Callback Queue 에 한 종류이다. 다른 하나는 Microtask Queue 인데 간략 설명을 위해 생략하겠음. Microtask Queue가 Task Queue 보다 우선순위가 높아 먼저 실행된다고 생각하고 넘어가자. |
| Event Loop | 비동기 함수들을 모니터링하면서 비동기 함수들을 다른 영역으로 옮겨주는 역할 Call Stack과 Callback Queue(Task Queue) 를 지속적으로 감시하면서 Call Stack이 비어있을 때만!!(매우 중요) Callback Queue에서 Call Stack 으로 함수를 옮겨준다. |
예시 코드
순서를 통해 다시 한번 정리해보자.
const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"), 500);
const baz = () => console.log("Third");
bar();
foo();
baz();
1. bar() 함수가 Call Stack에서 실행되는데 bar() 함수가 비동기 함수이네?
Web APIs로 이동시키고 bar() 함수는 Call Stack에서 지워진다. 이때부터 다른 스레드에서 bar() 함수를 관리한다.
2. foo() 함수가 Call Stack에서 실행되고 "First"가 출력되고 foo() 함수를 Call Stack에서 지운다.
3. baz() 함수가 Call Stack에서 실행되고 "Third"가 출력되고 baz() 함수를 Call Stack 에서 지운다.
4. Web APIs로 보내진 함수를 0.5초 뒤에 CallBack Queue로 이동한다.
5. Event Loop가 Call Stack과 CallBack Queue를 감시하면서 Call Stack 비워져 있는지 계속 확인한다. Call Stack이 비워져있는 것을 확인하면 CallBack Queue에 옮겨진 함수를 Call Stack으로 옮기고 "Second"가 출력되고 종료된다.
동작원리
해당 순서를 기억하면서 머릿속에 익히자 (한번 말고 3번은 보자)

출처: https://dev.to/lydiahallie