본문 바로가기

Javascript

[JaveScript] 이벤트 루프란? 작동 방식 자세히 알아보기 Event loops

반응형

 

JavaScript, 싱글 스레드 기반 언어 : 한번에 하나씩 작업 수행, 이벤트 루프를 이용해 비동기 방식으로 동시성 지원한다. 

 

이벤트 루프란 ? 

: Callback Event Queue에서 하나씩 꺼내서 동작시키는 Loop을 말한다. 위의 그림 전체를 말하는 것 같다. 

 

태스크 큐 ? 

: web api에서 비동기 작업들이 실행된 후 호출되는 콜백함수들이 기다리는 공간, FIFO, 하나의 큐로 이루어있지 않고 Microtask Queue, Animation Frames 등 여러개의 큐로 이루어져 있다. 

 

Web API ? 

: 브라우저에서 자체 지원하는 api이다. DOM이벤트, AJAX, setTimeout 등의 비동기 작업 등을 수행할 있도록 api 지원한다. 

 

 

이벤트 루프 프로세스

  1. 코드가 호출스택에 쌓이고 실행되면 자바스크립트 엔진은 비동기 작업을 Web API에게 위임
  2. Web API 해당 비동기 작업을 수행, 콜백 함수를 이벤트 루프를 통해 태스크 큐에 전달
  3. 이벤트 루프는 스택에 쌓여있는 함수가 없을 , 태스크 큐에서 대기하고 있던 콜백함수를 스택으로 넘겨준다. 
  4. 스택에 쌓인 콜백함수가 실행되고 실행된 함수는 제거된다. 

 

 


 

 

실습 

 

자바스크립트의 이벤트 루프(event loop)가 어떻게 tasks와 microtasks를 처리하는지에 대해 알아보좌

Task 에 들어가는 것과 microTask에 들어가는 것이 무엇인지 아는게 중요한 것 같다. 

 

 

 

console.log가 어떻게 찍힐지 맞춰보기 ! 

예제 1.

console.log('script start');

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

Promise.resolve()
  .then(() => {
    console.log('promise1');
  })
  .then(() => {
    console.log('promise2');
  })

console.log('script end');

 

정답

script start
script end
promise1
promise2
setTimeout

*하지만 Microsoft Edge, Firefox 40, ios safari, desktop safari 8.0.8에서는 setTimeout이 promise보다 먼저 찍힌다고 한다. 

 

실행 순서 

Script -> Tasks -> Microtasks 

setTimeout는 Tasks로 promise는 micotasks로 분류된다. 

 

 

 

예제 2 

// Let's get hold of those elements
var outer = document.querySelector('.outer');
var inner = document.querySelector('.inner');

// Let's listen for attribute changes on the
// outer element
new MutationObserver(function () {
  console.log('mutate');
}).observe(outer, {
  attributes: true,
});

// Here's a click listener…
function onClick() {
  console.log('click');

  setTimeout(function () {
    console.log('timeout');
  }, 0);

  Promise.resolve().then(function () {
    console.log('promise');
  });

  outer.setAttribute('data-random', Math.random());
}

// …which we'll attach to both elements
inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);

inner의 'click'이벤트 실행됨 -> onClickd 함수 실행 -> "click" 콘솔 찍힘 -> setTimeout - Task에 담아짐 -> Promise - microTasks에 담아짐 -> outer.setAttribute 실행 -> new MutationObserver - microTasks에 담아짐 -> microTasks에 담긴 promise, new mutationObserver 순차적 실행 -> "promise", "mutate" 콘솔 찍힘 -> microTasks 비워지면 바로 Tasks실행이 아니라 script 아래 outer 'click'이벤트 실행 -> onClick 함수 실행 -> "click" 콘솔 찍힘 -> setTimeout - Task에 담아짐 -> promise - microTasks에 담아짐 -> new MutationObserver - microTasks에 담아짐 -> microTasks 순차 실행 -> "promise" 콘솔 찍힘 -> "mutate" 콘솔 찍힘 -> Tasks에 담겨져 있던 setTimeout 두 개 실행 -> "timeout" 콘솔 찍힘 -> "timeout" 콘솔 찍힘 -> 끝 

 

 

찍히는 콘솔 로그

click
promise
mutate
click
promise
mutate
timeout
timeout

 

 

 

 

Reference : https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/

 

Tasks, microtasks, queues and schedules

 

jakearchibald.com

https://www.youtube.com/watch?v=8aGhZQkoFbQ&ab_channel=JSConf

https://www.youtube.com/watch?v=wcxWlyps4Vg&ab_channel=%EC%9A%B0%EC%95%84%ED%95%9CTech

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

https://zereight.tistory.com/855

 

이벤트 루프란?

- 이벤트 루프란 무엇인가요? Callback Event Queue에서 하나씩 꺼내서 동작시키는 Loop를 말한다. 자바스크립트는 싱글 스레드 기반 언어이기 때문에, 한번에 하나씩 작업을 진행한다. 그러나 자바스

zereight.tistory.com

 

반응형