[JS] 이벤트 루프

cabbage·2023년 3월 1일

JS

목록 보기
22/43
post-thumbnail

비동기

비동기 처리 방식은 현재 실행 중인 태스크가 종료되지 않더라도 다음 차례의 태스크를 바로 실행하는 방식이다.

  • 비동기 처리 방식은 현재 실행 중인 태스크의 종료 여부와 상관 없이 다음 태스크를 바로 실행하므로 태스크들이 block 상태가 되지 않는다.
  • 하지만 태스크 종료 여부와 상관 없이 태스크들을 실행하기 때문에 태스크들의 실행 순서를 보장할 수는 없다.
  • 대표적으로 비동기 통신, setTimeout 함수가 비동기 방식으로 동작한다.

이벤트 루프

자바스크립트의 비동기 처리 방식을 이해하려면 이벤트 루프 개념을 알아야 한다.

이벤트 루프는 콜 스택과 태스크 큐를 계속 확인하여, 태스크 큐에 대기 중인 함수를 콜 스택으로 옮겨준다.

  • 이벤트 루프는 콜 스택에 현재 실행 중인 함수가 있는지, 태스크 큐에 대기 중인 함수가 있는지를 반복해서 확인한다.
  • 콜 스택이 비워져 있고(현재 실행 중인 함수가 없고) 태스크 큐에서 대기 중인 함수가 있으면 해당 함수를 콜 스택으로 옮긴다.
  • 태스크 큐에서 콜 스택으로 이동한 함수가 실행된다.
  • 콜 스택에 담긴 함수를 자바스크립트의 메인 스레드가 실행한다. 실행이 종료된 함수는 콜 스택에서 비워진다.

setTimeout으로 이벤트 루프 이해하기

setTimeout 함수는 아규먼트로 콜백 함수와 ms 단위의 시간을 입력받는다. setTimeout 함수는 입력 받은 시간이 지난 뒤 콜백 함수를 실행하는 함수로, 비동기 함수이다.

const start = () => {
  console.log('시작!!');  // 1️⃣

  setTimeout(() => {     // 2️⃣
    console.log('0초 뒤에 실행됩니다!!');
  }, 0);

  let temp = 0;
  for (let i = 0; i < 9000000000; i++ ) { // 3️⃣
    temp++;
  }

  console.log(temp);      // 4️⃣
  console.log('끝!!');    // 5️⃣
};

start();

start 함수를 실행하면 코드는 1️⃣ -> 2️⃣ -> 3️⃣ -> 4️⃣ -> 5️⃣ 순서대로 실행된다. 하지만 코드 실행 순서와는 다른 결과가 출력되는 것을 확인할 수 있다. (1️⃣, 4️⃣, 5️⃣, 2️⃣ 순서대로 출력: '시작!!' -> 9000000000 -> '끝!!' -> '0초 뒤에 실행됩니다!!')

콜 스택, 태스크 큐, 이벤트 루프를 통해 이 결과가 어떻게 나오는지를 알 수 있다.

  1. start 함수가 콜 스택에 담기고 실행된다.
  2. 코드 1️⃣이 콜 스택에 담기고 실행된다. ('시작!!' 출력)

  1. 코드 2️⃣에서 setTimeout 함수는 비동기 함수다. 따라서 setTimeout의 콜백 함수가 태스크 큐에 담긴다.

  • setTimeout도 콜 스택에 올라갔다가 곧바로 콜 스택에서 비워진다.
  • 지정 시간(두 번째 아규먼트)만큼 Web API(브라우저의 경우)에 대기한다.
  • 그리고 setTimeout의 콜백 함수가 태스크 큐에 담긴다.
  1. 코드 3️⃣이 start 함수 내부에서 실행된다.

  1. 코드 4️⃣가 콜 스택에 담기고 실행된다. (9000000000 출력)

  1. 코드 5️⃣가 콜 스택에 담기고 실행된다. ('끝!!' 출력)

  1. start 함수가 종료되어 콜 스택이 모두 비워져 있으므로 이벤트 루프에 의해 태스크 큐에서 대기 중이던 setTimeout의 콜백 함수가 콜 스택에 담기고 실행된다. ('0초 뒤에 실행됩니다!!' 출력)

  • setTimeout 함수의 콜백 함수는 지정 시간(두 번째 아규먼트)인 0초 이후에 실행되지 않는다는 것을 확인할 수 있다.
  • 콜 스택이 비워질 때까지 태스크 큐에서 대기하는 시간이 필요하기 때문이다.
profile
캐비지 개발 블로그입니다. :)

0개의 댓글