[Frontend] Javascript의 Event Loop

이승준·2023년 3월 7일
0

Tlog.Frontend

목록 보기
3/3
post-thumbnail

Javascript의 작동원리

Javascript와 웹 브라우저가 작동하는 전체적인 그림을 표현하면 위와 같습니다.

Javascript 엔진에 heap과 콜 스택이 있으며 콜스택에 있는 함수들이 하나씩 pop되면서 해당 함수가 작동하게 됩니다. 이렇게 Javascript는 하나씩 pop되면서 한번에 하나의 동작밖에 실행하지 못하고 하나의 콜 스택만을 가지는 싱글스레드 언어입니다.

그래서 Javascript는 비동기 동작을 처리하기 위해 브라우저에서는 Web API, Node.js에서는 libuv라는 라이브러리를 이용하여 논-블로킹 I/O를 지원합니다.

🧱 여기서 논-블로킹 I(Input)/O(Output)이란, I/O 처리가 완료처리 됐을 때 결과를 회신하는 I/O 모델입니다.

Web API

여기서 Web API에 있는 DOM, ajax, setTimeout과 같은 것들은 Javascript 엔진인 V8에 존재하는게 아니며, 웹 브라우저에서 제공하는 Web API에 존재합니다.

Web API에 내장되어 있는 setTimeout함수나, DOM 객체에 존재하는 onClick이벤트는 이벤트 루프라는 것에 의해 관리되고 실행되는데요, 간단하게 아래의 예제 코드는 다음과 같은 순서로 작동하게 됩니다.

setTimeout(() => {
	console.log(2);
}, 0);

console.log(1);
  1. 콜 스택에 Web API의 setTimeout을 호출하는 함수를 올립니다.
  2. setTimeout을 Web API에 호출한 뒤에는 바로 콜 스택에서 제거됩니다.
  3. Web API에서 setTimeout에서 실행해야할 console.log(2)를 태스크 큐(위 그림에선 콜백 큐)에 넣습니다.
  4. console.log(1)가 콜 스택에 올려집니다.
  5. console.log(1)가 콜 스택에서 비워지면서 실행됩니다.
  6. 이벤트 루프는 콜 스택과 태스크 큐를 감시하면서 콜 스택이 비워지면, 태스크 큐에 있던 console.log(2)를 콜 스택에 올립니다.
  7. console.log(2)가 실행됩니다.

Event Loop

위에서 Javascript의 작동원리를 간단하게 보았는데요, Web API의 함수들이 태스크 큐에 추가되고, 콜 스택이 비워지면 이벤트 루프가 태스크 큐에 있는 함수를 콜 스택에 올린다는 사실을 알 수 있었습니다.
(참고로 FIFO, 먼저 추가된 태스트가 가장 먼저 나가는 구조 즉, 큐입니다)

그런데 이 이벤트 루프는 마이크로 태스트 큐도 지켜보는데요, 이 마이크로 태스크 큐에는 Promise의 then 메소드를 추가시키는데요, 여기서 추가된 마이크로 태스크는 일반 태스크보다 우선순위를 가지고 있습니다.

따라서 아래 코드의 출력결과는 다음과 같습니다.

setTimeout(() => {
	console.log('A');
}, 0);

Promise.resolve().then(() => {
	console.log('B');
}).then(() => {
	console.lob('C');
});
B
C
A

Promise의 then 메서드가 마이크로 태스크로서 우선순위를 가지게 됨으로, 콘솔에는 BC가 먼저 찍히게 됩니다. 그 이후 setTimeoutA가 찍히게 되죠.

마무리

Javascript는 싱글 스레드 언어이기 때문에 하나의 콜 스택을 가지고 여러가지 동작을 처리하게 되면 화면 렌더링이 느려저 최악의 사용자 경험을 제공하게 됩니다.

이를 해결하기 위해, 웹 브라우저에서는 Web API, Node.js에서는 libuv라는 라이브러리를 이용하여 비동기 동작 즉, 논-블로킹 I/O를 처리하며, 이벤트 루프는 이를 관장하여 콜 스택이 비워졌을 때 태스크 큐, 혹은 마이크로 태스크 큐에 있는 작업들을 콜 스택으로 올려줌으로써 멀티 쓰레딩처럼 작업합니다.

profile
인터랙티브 웹부터 풀스택, web3 등 다양한 분야에 관심을 가지고 다양한 일을 이루기위한 수단으로서 개발합니다.

0개의 댓글