이벤트루프 개념 정리
23 December, 2021 - 5 min read
단일 스레드 자바스크립트
자바스크립트는 단일 스레드 언어로 유명하다. 운영체제로 부터 시스템 자원을 할당받아 메모리에 올라와 실행되고 있는 프로그램의 인스턴스를 프로세스라고 하는데, 이러한 프로세스들은 각각 독립된 메모리 영역을 차지한다. 스레드는 이러한 프로세스가 할당받은 자원을 이용하는 실행의 단위를 의미한다. 멀티스레드로 동작을 먼저 살펴보면, 프로세스 내에서 각각의 스레드는 레지스터와 스택을 별도로 따로 할당받고, 프로세스내의 다른 스레드와 code,data,heap 영역은 공유한다.
브라우저나 노드 환경의 구성요소를 살펴보면 다음으로 대략 말할 수 있는데,
- 자바스크립트엔진 콜스택
- 태스크 큐
- WebAPI
자바스크립트 엔진이 단일 호출 스택을 사용한다는 점에서 단일 스레드라고 불리운다. 호출스택은 스택이므로 들어있는 함수가 실행을 마치고 제거되기전까지는 다른 어떠한 함수도 실행될수 없다. 이럼에도 불구하고 자바스크립트가 비동기로 동작하며 많은일을 할 수 있는 이유는 태스크큐와 이벤트루프때문이다.
태스크큐
태스크 큐는 말 그대로 콜백 함수들이 대기하는 큐(FIFO) 형태의 배열이라 할 수 있고, 이벤트 루프는 호출 스택이 비워질 때마다 큐에서 콜백 함수를 꺼내와서 실행하는 역할을 해 준다.
모든 비동기 API들은 작업이 완료되면 콜백 함수를 태스크 큐에 추가한다. 이벤트 루프는 '현재 실행중인 태스크가 없을 때'(주로 호출 스택이 비워졌을 때) 태스크 큐의 첫 번째 태스크를 꺼내와 실행한다. 모든 비동기 방식의 API들은 이벤트 루프를 통해 콜백 함수를 실행한다. (콜백 내부에 모두 try catch를 해주어야 한다. 콜백안에 콜백이 있을경우 내부 콜백은 외부콜백이 스택에서 제거된이후 독립적인으로 스택에서 동작하게 되기 때문이다.)
setTimeOut도 비동기 API중 하나로 호출스택에 바로 올라가지않고 태스크큐에 추가된다.
이벤트루프
그렇다면 프로미스의 경우에는 어떨까? 프로미스는 마이크로태스크라고해서 일반 태스크보다 더 높은 우선순위를 지닌다. 이 마이크로 태스크는 일반 태스크큐가 아닌 마이크로태스크큐에 담딘다. 마이크로태스크큐는 태스크큐보다 우선순위에 있기때문에 만약 setTimeout과 promise를 같이사용하면 프로미스에 등록한 콜백이 먼저 실행되게된다. 계속 마이크로 태스크가 실행이되어 그냥 일반 태스크가 지연되는 경우가 있을 수 있으니 주의해야겠다!