이벤트 루프(Event Loop)에 대해 알아보자!

Jetom·2024년 7월 5일
0

개념정리(js)

목록 보기
19/20
post-thumbnail
post-custom-banner

console.log와 web api를 쓰면서 console.log가 왜 먼저 동작하는지 궁금했지만 정작 찾진않았다.(과거의 나 반성해라..) 그런데 멘토님이 멘토링 시간에 이벤트 루프가 뭔지 공부해보라 하셔서 그 계기로 글을 쓰게되었다 ㅎㅎ 소스 제공 감사합니당 😊


이벤트 루프란?

자바스크립트는 싱글 스레드로 동작한다. 하지만 브라우저가 동작하는 것을 살펴보면 많은 태스크가 동시에 처리되는 것처럼 느껴진다. 예를 들어, HTML 요소가 애니메이션 효과를 통해 움직이면서 이벤트를 처리하고, HTTP 요청을 통해 서버로부터 데이터를 가지고 오면서 렌더링하기도 한다. 이처럼 자바스크립트의 동시성을 지원하는 것이 바로 이벤트 루프이다.

싱글 스레드 → 한 번에 하나의 일만 수행할 수 있는것을 의미
스레드 → 프로세스의 실행 단위

싱글 스레드에 대해서도 해야할 말이 많지만 간단히 개념만 설명하고! 추후에 블로그에 써보겠당 😎


브라우저 환경

갑자기 브라우저 환경에 대한 얘기가 왜 나오냐고 묻는다면 아래와 같이 설명하려한다. JS는 비동기 작업이 가능하려면 JS 엔진을 구동하는 환경(브라우저나 Node.js)가 필요하다. 그렇기에 브라우저 환경을 알아야하는데 어떻게 되어있는지 아래 그림으로 확인하자.


그림 출처 - https://poiemaweb.com/js-event

❗ 해당 그림에는 마이크로 태스크 큐, 매크로 태스크 큐, 애니메이션 프레임가 없는데 이 세 가지는 이벤트 큐(=태스크 큐 or 콜백 큐)에 들어가있다.

그림에서 보이듯 역할이 여러가지로 나뉘어져 있는것이 보이는데, 다음은 각자 하는 역할을 정리한 것이다.

  • Call Stack(호출 스택)
    • 작업이 요청되면 순차적으로 Call Stack에 쌓이게 되고 순차적으로 실행됨. JS는 하나의 Call Stack을 사용하기 때문에 해당 태스크가 종료가 되면 다음 태스크가 실행된다.(LIFO 구조로 동작함)
  • Heap
    • 동적으로 생성된 JS 객체가 저장되는 메모리 공간

❗ JS의 엔진은 Call stack과 Heap이고, 밑의 나머지 설명들은 웹 브라우저의 구조에 대한 설명이다.

  • Web API

    • 브라우저에서 제공하는 API모음으로, 비동기적으로 실행되는 작업을 전담하여 처리
    • setTimeout, DOM 이벤트, HTTP 요청(fetch), WebSocket등이 있음
    • JS 엔진 외부에서 실행되고, 비동기 작업이 완료되면 콜백 큐에 콜백 함수를 추가

  • Callback Queue(= Event Queue)
    - 비동기 작업이 완료되면 실행될 함수들이 대기하는 공간
    - 타이머, 네트워크 요청, 사용자 인터페이스 이벤트 등이 완료되면 해당 콜백이 이벤트 큐에 들어감
    - 브라우저 런타임이나 Node.js 런타임이 담당함

콜백 큐에는 마이크로 태스크 큐와 매크로 태스크 큐와 애니메이션 프레임이 별도로 존재함.
마이크로 태스크 큐 → 애니메이션 프레임 → 매크로 태스크 큐순으로 실행된다. (마이크로 태스크 큐가 비어있으면 애니메이션 프레임이 실행되고, 애니메이션 프레임이 비어있으면 매크로 태스크 큐가 실행됨)

  • 마이크로 태스크 큐(Micro Task Queue)
    • 프로미스의 'then', 'catch', 'finally' 메서드에 의해 예약된 콜백들이 이곳에 속함
    • 매우 빠르게 처리되어야 하는 작업을 위한 것

💡 fetch나, axios같은 네트워크 요청(=매크로 태스크 큐)은 마이크로 태스크 큐에 직접 포함되진 않지만 .then() 콜백은 마이크로 태스크 큐에 포함된다.

  • 매크로 태스크 큐(Macro Task Queue)

    • 'setTimeout', 'setInterval'같은 타이머 함수들에 의해 예약된 콜백들이 이곳에 속함
    • 'event listener'같은 특정 이벤트가 발생했을때 호출되는 함수도 이곳에 속함
    • 비교적 덜 긴급한 작업을 위해 사용
  • 애니메이션 프레임(Animation Frames)
    - 'requestAnimationFrame'을 통해 등록된 콜백들을 의미(웹 브라우저에서 애니메이션을 부드럽게 실행하기 위한 메커니즘)


  • Event Loop

    • 비동기 함수들을 적절한 시점에 실행시키는 관리자. 이벤트 루프는 콜 스택과 콜백 큐를 모니터링하며, 콜 스택이 비어 있는 경우 콜백 큐에서 함수를 가져와 실행(비동기 작업이 순차적으로 실행됨)
  • Event Table

    • 특정 이벤트(setTimeout, click 등)가 발생했을 때 어떤 콜백 함수가 호출되어야 하는지 알고 있는 자료구조

이벤트 루프의 역할

브라우저 환경을 알았다면 이벤트 루프가 무슨 역할을 하는지 알아보자. 이벤트 루프의 주요 역할은 JS가 비동기적으로 작업을 처리할 수 있게 하는 것이다. 그래서 JS는 싱글 스레드 기반의 언어이며 논 블록킹에 동시성을 지원한다고 한다. 아래의 내용은 이벤트 루프가 하는 역할에 대해 간단히 설명한 내용이다.

  • 콜 스택 모니터링
    • 이벤트 루프는 콜 스택을 지속적으로 모니터링
    • 콜 스택이 비어 있는지 확인하고 비면 작업을 처리
  • 콜백 큐 확인
    • 콜 스택이 비어 있을 때, 콜백 큐에서 작업을 가져옴
    • 콜백 큐에는 비동기 작업이 완료된 후 실행될 콜백 함수들이 대기중
  • 작업 전달
    • 콜백 큐에서 작업을 가져와 콜 스택에 추가

예시 코드

학습한 내용을 바탕으로 코드를 구성했다. 아래의 코드 순서가 있을 때 어떤 순서대로 작업이 완료되는지, 그 이유가 무엇인지 설명할 수 있다면 대략적으로 이벤트 루프에 대해 알게된 것이다.

const API_URL = "https://jsonplaceholder.typicode.com/todos/1";

console.log("Hello");

setTimeout(() => {
  console.log("setTimeout은 매크로 태스크 큐!!");
}, 1000);

console.log("Hi");

const promise = fetch(API_URL)
  .then((res) => {
    if (!res.ok) {
      throw new Error("promise error");
    }
    return res.json();
  })
  .then((data) => console.log("promise Data:", data))
  .catch((err) => console.log("err:", err));

console.log("Jetom");

정답은 아래와 같다!
1. "Hello" 출력: 동기적으로 실행되어 즉시 출력
2. "Hi" 출력: 동기적으로 실행되어 즉시 출력
3. "Jetom" 출력: 동기적으로 실행되어 즉시 출력
4. 'setTimeout': 매크로 태스크 큐에 추가
5. 'fetch': 요청이 시작되고, 프로미스의 'then' 콜백이 마이크로 태스크 큐에 추가
6. 콜 스택이 비어 있으면 이벤트 루프는 마이크로 태스크 큐의 작업을 처리
7. "promise Data": "promise Data:", data 출력
8. 마이크로 태스크 큐가 비어 있으면, 이벤트 루프는 매크로 태스크 큐의 작업을 처리
9. "setTimeout": "setTimeout은 매크로 태스크 큐!!" 출력

따라서 Hello 👉 Hi 👉 Jetom 👉 fetch 👉setTimeout 순으로 콘솔이 출력된다!


👇 해당 유튜브 영상은 매크로 태스크 큐(=태스크 큐) 마이크로 태스크 큐(=잡 큐)에 대해서도 같이 나오는 쇼츠이다. 영상 속 나오는 코드가 작아서 보는데 불편하지만 어느정도 이해하는데 도움은 줄수있다.

https://youtube.com/shorts/m8biTN2fBEs?si=JvocvZmCoxaIqiyO

출처 -
모던 자바스크립트 Deep Dive
https://poiemaweb.com/js-event
ChatGPT

profile
사람이 좋은 인간 리트리버 신혜리입니다🐶
post-custom-banner

0개의 댓글