이벤트 루프

2021. 11. 16. 21:59웹 프론트엔드 깊게 이해하기/자바스크립트 이해하기

이 글은 아래 링크의 내용을 바탕으로 작성되었습니다.

https://www.youtube.com/watch?v=cCOL7MC4Pl0

 

이벤트 루프란?

 

자바스크립트의 단일 스레드 환경에 맞춰서 비동기 처리와 이벤트 핸들링을 수행하는데 사용되는 제어방식입니다. 간단히 설명하자면, 끊임없이 콜스택의 상태를 감지하며 태스크 큐의 콜백을 콜스택에 밀어넣는 방식입니다.

 

 

 

왜 자바스크립트는 단일스레드 방식을 택한 것일까?

 

이벤트 루프의 배경에는 흔히 자바스크립트가 '단일 스레드로만 동작한다'는 사실이 깔려 있습니다. 하지만 다른 언어들은 스레드를 나누는 일이 흔한데, 왜 하필 자바스크립트는 단일 스레드를 고집하는 것일까요? 이는 자바스크립트의 주요 실행 환경이 브라우저라는 점에 기반합니다. 이용자가 발생시킨 이벤트와 서버 요청에 대한 응답이 언제 처리되어야 하는 지를 예측할 수 없기 때문에 스레드를 나누어 연산 능력을 떨어뜨리기보다는 하나의 스레드로 모든 처리를 빠르게 수행하는 것을 자바스크립트는 선택한 것입니다. 그리고 이를 이벤트 루프가 보조하여 비동기 처리와 이벤트 핸들링이 지금처럼 수행될 수 있는 것이죠.

 

 

 

왜 이벤트 루프의 방식이 필요했던 것일까?

 

하지만 잘 생각해보면 브라우저는 굳이 이벤트 루프 방식을 택할 이유가 없어보이기도 합니다. 비동기적으로 실행시켜야 할 함수가 필요하면 그냥 여러 일을 동시에 왔다 갔다하면 그만이고 이벤트 핸들링은 그냥 이벤트가 발생하는 대로 바로 핸들러를 콜스택에 넣어버리면 되는 일 아닐까요? 굳이 콜백 큐니 뭐니 하는 것들이 필요한 이유가 뭘까요?

 

 

병렬 처리

 

병렬처리가 선택될 수 없는 이유는 분명합니다. 처리에 걸리는 시간에 따라서 나중에 추가된 콜백이 이전에 추가된 콜백보다 먼저 수행될 수 있기 때문입니다. 각 콜백은 서로 먼저 수행되기 위한 '경쟁상태'에 놓이게 되고 이러면 개발자는 정확히 어떠한 순서로 렌더링이 수행될지 예측하기 어려워집니다.

 

 

only 콜스택

 

이벤트와 비동기 처리가 오직 콜스택을 통해서만 일어나게 된다면 '중요한 일을 먼저 처리'하는 것이 불가능해집니다. 예를 들어 서버로부터 응답이 도착해서 그 응답 결과를 화면상에 반영해야 하는 경우, 만일 그 전에 너무나 많은 스택들이 쌓여 있을 때 그 일은 한참 뒤로 밀리고 말 것입니다. 이렇듯 단순히 콜스택만 있다면 더 중요한 일에 우선순위를 매기는 작업이 불가능해집니다.

 

 

 

이벤트 루프는 어떤 식으로 동작할까?

 

 

(출처 : https://www.youtube.com/watch?v=cCOL7MC4Pl0)

 

위의 그림을 통해 이벤트 루프의 동작을 한눈에 볼 수 있습니다. 태스크 큐에 콜백이 담겼지만 콜스택은 비어있다면 이벤트루프는 이를 감지하여 해당 콜백을 처리합니다. 만일 그 콜백이 렌더링 프로세스를 트리거한다면 렌더링이 수행됩니다. 중요한 것은 이 한번의 사이클이 콜백 하나당 하나씩 수행된다는 것입니다.

 

 

 

이벤트 루프가 콜백의 우선순위를 결정하는 방법

 

결론적으로 말해서, 이벤트 루프는 태스크 큐의 종류를 3가지로 나눔으로써 우선순위를 구현합니다. 1순위는 프라미스 콜백이 담기는 마이크로태스크큐, 2순위는 requestAnimationFrame 함수의 콜백이 담기는 애니메이션 콜백큐, 3순위는 이벤트 핸들러와 setTimeout, setInterval 등의 webAPI 를 통해 넘겨진 콜백이 담기는 매크로태스크큐입니다. 이벤트 루프는 1순위 큐부터 차례로 조회하면서 해당 순위에 위치한 콜백들이 모두 비워지기까지 다음 순위에 있는 태스크 큐의 콜백을 처리하지 않습니다.

 

물론 예외는 있습니다. 애니메이션 콜백은 화면의 주파수에 맞춰서 실행되기 때문에 해당 큐 안에 담긴 콜백들이 모두 비워져 있지 않더라도 다음 프레임까지 여유가 있다면 매크로태스크큐 안의 콜백이 콜스택에 담기는 것을 허용합니다.