기억 휘발 방지소

[JavaScript] 이벤트 루프 본문

Web/JavaScript

[JavaScript] 이벤트 루프

choice91 2021. 9. 2. 23:34
728x90
반응형

이번 글에서는 JavaScript의 이벤트 루프에 대해 정리해보려고 한다.

 

javascript.info에서는 이벤트 루프를 다음과 같이 설명하고 있다.

이벤트 루프는 태스크가 들어오길 기다렸다가 태스크가 들어오면 이를 처리하고 처리할 태스크가 없는 경우엔 잠드는, 끊임없이 돌아가는 자바스크립트 내 루프

 

이벤트 루프의 동작방식을 대충 그려봤다.

동작원리

자바스크립트에서 함수를 호출하게되면 Call Stack에 쌓인다. 쌓인 역순으로 실행하게 된다.

setTimeout, AJAX 또는 DOM event 함수를 실행하면 Call Stack에서 Web API로 보내고 정해진 시간 등이 지나면 Task Queue로 보내게 되고 순차적으로 쌓인다. 

Task Queue에 쌓인 Callback들은 Call Stack이 비었을 때 Event Loop에 의해 Call Stack으로 다시 보내지고 Call Stack에서 꺼내어 실행하게 된다.

 

아주 간단한 예제를 들어보자면

function second() {
  console.log(2);
}

console.log(1);

setTimeout(second, 1000);

console.log(3);

실행하면 어떤 결과가 나올까?

'1 2 3' 이 나올거라고 생각한다면 틀렸다. 

 

정답은 아래처럼 나온다.

1
3
2

 

왜 저렇게 나오는지 이벤트 루프를 생각하며 살펴보자

 

1. 가장 먼저 console.log(1)이 Call Stack에 push된다.

Call Stack: console.log(1)
Web API: 
Task Queue: 
콘솔출력: 

 

2. Call Stack에 있는 console.log(1)이 실행되고 Call Stack에서 제거된다. 콘솔에는 1이 출력된다.

Call Stack: 
Web API: 
Task Queue: 
콘솔출력: 1

 

3. setTimeout을 Call Stack으로 push한다.

Call Stack: setTimeout()
Web API: 
Task Queue: 
콘솔출력: 1

 

4. setTimeout은 Web API로 보내고 주어진 시간(1000ms)만큼 기다린다.

Call Stack: 
Web API: timer(second, 1000)
Task Queue: 
콘솔출력: 1

 

5. Call Stack에 console.log(3)을 push한다.

Call Stack: console.log(3)
Web API: timer(second, 1000)
Task Queue: 
콘솔출력: 1

 

6. console.log(3)이 실행되고 콘솔에 3이 출력된다.

Call Stack: 
Web API: timer(second, 1000)
Task Queue: 
콘솔출력: 1
                   3

 

7. 대기하던 Callback함수가 1초 후 Task Queue로 간다.

Call Stack: 
Web API: 
Task Queue: second
콘솔출력: 1
                   3

 

8. Call Stack이 비었으면 이벤트 루프에 의해 Task Queue에 있는 second가 Call Stack으로 가게된다.

Call Stack: second
Web API: 
Task Queue: 
콘솔출력: 1
                   3

 

9. second함수가 실행되고 console.log(2)가 콘솔에 출력된다.

Call Stack: 
Web API: 
Task Queue: 
콘솔출력: 1
                   3
                   2

 

 

우선순위

아쉽게도 Task Queue에서 Promise가 setTimeout보다 우선순위가 높아 setTimeout이 Promise보다 Task Queue에 먼저 들어왔어도 Promise가 먼저 실행된다.

 

간단한 예시이다.

function run() {
  console.log("시작");

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

  new Promise((resolve) => {
    resolve("Promise");
  }).then((result) => {
    console.log(result);
  });

  console.log("끝");
}

run();

결과를 먼저보면 아래와 같이 나온다.

시작

Promise
setTimeout

setTimeout보다 Promise가 먼저 실행되어 콘솔에 Promise가 먼저 출력되는 것을 볼 수 있다.

728x90
반응형

'Web > JavaScript' 카테고리의 다른 글

[JavaScript] Promise  (0) 2021.09.04
[JavaScript] parseInt() vs Number()  (0) 2021.09.03
[JavaScript] 호출스택  (0) 2021.08.31
[JavaScript] Set을 Array로 바꾸는 방법  (0) 2021.08.30
[JavaScript] 함수 선언식과 함수 표현식  (0) 2021.08.28