콜스택은 LIFO 구조 (Last In First Out)
태스크큐는 FIFO 구조 (First In First Out)
이런 함수가 있다고 가정해보자
const onClickBtn = () => {
console.log("시작")
setTimeout(() => {
console.log("1초 뒤에 실행 될 거에요")
},1000)
let sum =0;
for(let i = 0; i <= 90000000; i++) {
sum+= 1;
}
console.log("끝")
}
버튼을 누르면 onClickBtn이라는 함수가 실행된다. 그럼 onClickBtn의 내부 실행 순서는 어떻게 될까 ?
처음에 생각하기로 나는 당연히
1. console.log("시작")
2. console.log("1초 뒤에 실행 될 거에요")
3. console.log("끝")
이라고 생각했는데 막상 실행하니 아래와 같은 순서로 진행됐다.
holy moly ..
구조를 까보자 !

콜스택에 onClickBtn이라는 함수가 들어가면, 그 안에 내용들이 실행된다.
이 때 setTimeout 같이 오래 걸리는 함수들은 컴퓨터가 미리 빼서 후처리 하는데, 콜스택에 아무것도 없을 때 까지 대기를 탄다. 그 대기를 타는 장소가 "태스크큐"다.
그래서 콘솔에 시작이 나오고 끝이 나온거다.
그럼 이제 끝이라는 콘솔까지 찍히면, onCLickBtn 함수는 실행시킬 것을 다 했으니 콜스택에서 사라진다. 이제서야 콜스택이 비어있어 태스크큐에 빠져있던 setTimeOut의 콜백함수가 콜스택으로 들어가 실행된다.
이렇게 처리되는 것을 하는 게 스레드라고 하고, 자바스크립트는 스레드가 하나 있어 싱글스레드 혹은 이벤트루프스레드 라고 부르고 다른 언어는 스레드가 여러 개라 멀티스레드라고 부른다.
이미지처럼 빙글빙글 돌아가는 구조를 "이벤트루프" 라고 부른다.

멀티스레드가 싱글스레드 보다 일꾼이 많으니 더 빠른 것 아니냐고 할 수 있지만, 정작 실제로 일을 하는 건 CPU고 스레드는 가상 일꾼이다. 그래서 멀티스레드는 동시에 여러가지 일이 한번에 처리되는 개념보다는 동시처리 되는 느낌을 주는 분업의 개념이다. 각자 할당량이 있고 그걸 다 하면 다음 스레드가 이어서 처리하는 것이다. (이런것을 컨텍스트 스위칭이라고 한다) 그래서 멀티스레드가 싱글스레드보다 빠르다거나 그런건 없고 오히려 싱글스레드가 속도 측면에서는 더 빠르다.
대신 ! 싱글스레드는 엄청 오래 걸리는 일이 있다면, 하루종일 오래 걸리는 일을 하고 나서야 다음 일을 할 수 있는데, 멀티스레드는 조금씩 하고 다음 스레드로 넘어가니까 병목이 생기지 않는다.
물론 아까처럼 setTimeout이나, 외부 데이터 가져오는 등과 같은 오래 걸리는 일을 태스크큐나 마이크로큐에 빼고 빨리 끝나는 일을 먼저 처리하지만 for문 같은 것은 큐로 빠지지가 않는다. 그래서 가급적이면 for문 같이 CPU 계산량이 많은 작업들은 지양하는 게 좋다.
정리하면 100가지의 일을 처리하는 하나의 함수보다는 백개의 함수가 일을 하나씩 처리하는 구조가 자바스크립트와 같은 싱글스레드 구조한테는 적합하다.