비동기 프로그래밍 1편 - 이벤트 루프
Javascript
는 싱글스레드로 동작하는 언어입니다. 메인 스레드, 하나의 스레드로 구성되어 있기 때문에 한번에 하나의 작업만 수행할 수 있습니다. 다른 작업이 중간에 끼어들 수도 없고, 기존에 수행하던 작업이 끝나야만 그 다음 작업을 수행할 수 있습니다. 예를들어 20초가 걸리는 일을 수행한다고 하면 그 일을 처리하는 20초 동안 아무것도 할 수 없습니다.
그럼 어떻게 자바스크립트는 비동기를 처리 할 수 있을까? 라는 질문이 생기는데 그의 답은 브라우저는 자바스크립트 엔진 자체가 제공하지 않는 웹 API 기능을 제공합니다. 이 API는 DOM API, setTimeout, HTTP requests
등이 포함되고 이것이 비동기 동작을 만드는 데 도움을 줍니다.
자바스크립트가 런타임에서 비동기 처리를 하는 방법

위 사진은 자바스크립트가 런타임 환경에서 비동기를 어떻게 처리하는지 관한 사진입니다. 하나씩 살펴 보겠습니다
호출 스택 (콜스택)
일반적으로 우리가 호출하는 함수를 말하며 스택에 순차적으로 쌓이고 스택의 맨 위에서부터 아래로 한 번에 하나의 함수만 처리할 수 있습니다.
Heap (힙)
자바스크립트 엔진에 호출 스택과 같이 속해있습니다. 변수와 함수의 저장 그리고 호출 등의 작업이 발생하는 공간이며 메모리 할당을 한는 공간을 말합니다.
Event Loop (이벤트 루프)
콜스택과 이벤트큐를 주시하며 콜스택이 비어있다면 이벤트큐에 있는 스택을 콜스택으로 이동한 후 실행하는 것을 말합니다.
Web APIs
우리가 자주 사용하는 setTimeout이나 AJAX 같은 비동기 호출, 이벤트들을 담당하며 콜백 함수를 이벤트 큐(테스크큐)에 저장합니다
이벤트 큐 (Task Queue)
Web API에서 보내진 비동기 처리가 모이는 곳이며 종류가 여러가지 있습니다.
- 매크로태스크 큐 (Macrotask Queue)
WebAPI로 전달된 비동기 작업이 setTimeout(), setInterval() 또는 setImmediate() 라면 지정된 시간만큼 실행하고 콜백함수를 이곳에 보냅니다.
- 마이크로태스크 큐 (Microtask Queue)
WebAPI로 전달된 비동기 작업이 Promise()나 async/await라면 then(), catch(), finally() 같은 콜백함수를 이곳에 보냅니다.
- 애니메이션 큐 (request Animation Frame Queue)
WebAPI로 전달된 애니메이션 관련 콜백함수를 이곳에 보냅니다.
requestAnimationFrame이란?
사람은 1초에 60개의 프레임을 볼 수 있어 16.6ms마다 프레임을 찍어내면 됩니다. setInterval이나 setTimeout으로도 구현이 가능하지만 이들은 프레임을 신경쓰지 않고 동작하기 때문에 애니메이션 코드를 실행하는데 16.6ms가 넘게 걸린다면 16.6ms동안 프레임을 찍어내지 못했기 때문에 화면이 끊기는 듯한 현상이 발생할 수 있습니다. 이들은 프레임 시작시간에 맞춰 함수가 시작되는 것이 아니라 중간쯤부터 시작해 프레임 시간을 초과해버리게 됩니다. requestAnimationFrame을 사용하면 프레임 생성 시작시간에 맞춰 애니메이션 코드를 시작할 수 있고 최적화된 속도로 부드러운 애니메이션을 표현하면서 성능도 확보할 수 있습니다.
이벤트 큐 순서
마이크로태스크 > 애니메이션 > 매크로테스크 이다
이벤트 루프 작동과정
자바스크립트가 이벤트 루프를 통해 어떻게 비동기 처리하는지 설명해보겠습니다.

console.log(1)
이 stack(콜 스택) 에 추가됩니다 그리고console.log(1)
이 실행되면 console창에 출력되고 stack(콜 스택)에서 삭제 됩니다.- 그 다음
setTimeout(function cb() {..})
이 stack(콜 스택)에 추가되는데setTimeout
은 Brower에서 제공하는 timer 기능을 실행하여 콜백함수를Web APIs
로 이동 후 stack(콜 스택)에서 삭제 됩니다. console.log(3)
이 stack(콜 스택) 에 추가됩니다 그리고console.log(3)
이 실행되면 console창에 출력되고 stack(콜 스택)에서 삭제 됩니다.- 이제 시간이 흘러
setTimeout
함수에 전달한 시간 5초가 흐르면 콜백 함수가 바로 stack(콜 스택)에 추가되는 것이 아닌 task queue(이벤트 큐)로 이동하여 기다립니다. - 이벤트 루프는 콜스택이 비어있다는 것을 확인하면 task queue(이벤트 큐)에 있는 함수를 콜스택으로 이동하여 실행합니다.
- console창에
console.log(2)
를 출력한 후 stack(콜 스택)에서 삭제 됩니다.