브라우저 + JS 작동원리 : 이벤트 루프

윤뿔소·2024년 7월 13일

기술 | JavaScript

목록 보기
1/4

JS가 브라우저에서 실행되면 어떤 과정인지, 여기서 JS만의 신기한 기능인 이벤트 루프에 대해서 작성해보겠습니다.

이벤트 루프

자바스크립트는 단일 스레드 언어로, 한 번에 하나의 작업만 실행할 수 있습니다. 이벤트 루프는 비동기 작업을 관리해 프로그램이 멈추지 않고 실행될 수 있도록 합니다.

1. 콜 스택(Call Stack)

함수가 호출되면 콜 스택에 추가되고, 함수가 실행을 완료하면 스택에서 제거됩니다.

  1. greet() 함수가 호출돼 콜 스택에 추가됩니다.
  2. greet() 함수가 "Hello!"를 반환하고 콜 스택에서 제거됩니다.
  3. respond() 함수가 호출돼 콜 스택에 추가됩니다.
  4. respond() 함수 내의 setTimeout웹 API로 전달됩니다.
  5. setTimeoutrespond() 함수가 값을 반환하고 콜 스택에서 제거됩니다.

2. 웹 API(Web API)

비동기 작업(예: setTimeout)은 브라우저의 웹 API를 통해 처리됩니다. 이 작업은 완료된 후 큐(Queue)에 콜백 함수를 추가합니다.

  • 과정 설명:
    1. respond() 함수가 호출되면 setTimeout 함수가 콜 스택에 추가됩니다.
    2. setTimeout 함수가 웹 API로 콜백을 전달하고 콜 스택에서 제거됩니다.
    3. 웹 API에서 타이머가 1000ms 동안 작동합니다.

3. 큐(Queue)

타이머가 만료되면 콜백 함수가 바로 콜 스택에 추가되는 것이 아니라 큐(Queue)에 추가됩니다. 이때, 이벤트 루프가 큐와 콜 스택을 연결하는 역할을 합니다.

  1. 타이머가 1000ms 동안 실행됩니다.
  2. 타이머가 완료되면 콜백 함수가 콜백 큐에 추가됩니다.

4. 이벤트 루프

  1. 콜 스택이 비어 있는 경우, 이벤트 루프는 큐에서 첫 번째 항목을 콜 스택으로 이동시킵니다.
  2. 콜백 함수가 실행되고 값을 반환한 후 콜 스택에서 제거됩니다.

예시

const foo = () => console.log('First');
const bar = () => setTimeout(() => console.log('Second'), 500);
const baz = () => console.log('Third');

bar();
foo();
baz();

실행 과정

  1. bar() 호출: setTimeout이 웹 API로 보내지고, bar는 스택에서 제거됨.
  2. foo() 호출: "First" 출력 후 스택에서 제거됨.
  3. baz() 호출: "Third" 출력 후 스택에서 제거됨.
  4. 타이머 완료 후 콜백이 큐로 이동.
  5. 스택이 비면 콜백이 실행돼 "Second" 출력.

출처: Lydia Hallie

추가: 비동기 예시 순서도

let myFirstPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Success!");
  }, 1000);
});

myFirstPromise.then((successMessage) => {
  console.log("Yay! " + successMessage);
});

이 코드의 실행 순서는 다음과 같습니다:

  1. new Promise(...) 생성자가 호출됩니다.

    • Promise 객체가 생성되고 myFirstPromise 변수에 할당됩니다.
    • Promise 생성자의 executor 함수가 즉시 실행됩니다.
  2. setTimeout 함수가 호출됩니다.

    • 1초(1000ms) 후에 실행될 콜백 함수가 JavaScript의 이벤트 루프에 등록됩니다.
    • setTimeout은 비동기 함수이므로, 타이머 설정 후 즉시 다음 코드로 넘어갑니다.
  3. myFirstPromise.then(...) 메서드가 호출됩니다.

    • then에 전달된 콜백 함수가 Promise의 성공 처리기(handler)로 등록됩니다.
    • 이 시점에서 Promise는 아직 대기(pending) 상태입니다.
  4. 동기적인 코드의 실행이 모두 완료됩니다. 이벤트 루프는 비동기 작업을 기다립니다.

  5. 약 1초 후, setTimeout의 콜백 함수가 실행됩니다.

    • resolve("Success!") 함수가 호출됩니다.
    • Promise의 상태가 이행(fulfilled)으로 변경됩니다.
  6. Promise가 이행되었으므로, then에 등록된 콜백 함수가 다음 마이크로태스크 큐에 추가됩니다.

  7. 이벤트 루프는 마이크로태스크 큐에서 then의 콜백 함수를 가져와 실행합니다.

    • console.log("Yay! " + successMessage);가 실행되어 "Yay! Success!"가 콘솔에 출력됩니다.

주요 포인트

  • Promise 생성과 then 메서드 호출은 동기적으로 즉시 실행됩니다.
  • setTimeout의 콜백과 Promise 해결 후의 then 콜백은 비동기적으로 나중에 실행됩니다.
  • Promise의 처리(resolve 호출)와 then 콜백의 실행 사이에는 약간의 시간 차이가 있을 수 있습니다 (마이크로태스크 큐를 통해 처리되기 때문).
profile
코뿔소처럼 저돌적으로

0개의 댓글