이벤트루프(eventloop)란 (feat. Call Stack)

2024-03-24

  • JavaScript
  • FE

이벤트 루프(Event Loop)는 비동기 방식으로 작동하는 프로그래밍 모델에서 중요한 역할을 하는 구성 요소입니다. 특히 JavaScript와 같은 단일 스레드 환경에서는 이벤트 루프가 중요한 핵심 기술입니다. 이벤트 루프의 주요 목적은 프로그램의 실행 흐름을 관리하고, 비동기 작업의 결과를 처리하며, 사용자 이벤트(클릭, 키보드 입력 등)를 처리하는 것입니다.

이벤트 루프의 작동 원리

  1. 태스크 큐(Task Queue) : 비동기 작업(예: setTimeout, HTTP 요청)의 콜백 함수가 실행될 준비가 되면, 이 함수들은 태스크 큐(또는 이벤트 큐)에 추가됩니다.

  2. 마이크로태스크 큐(Microtask Queue) : 프로미스(Promise)와 같은 더 미세한 비동기 작업의 콜백은 마이크로태스크 큐에 추가됩니다. 마이크로태스크 큐는 태스크 큐보다 우선 순위가 높아, 태스크 큐의 작업들보다 먼저 처리됩니다.

  3. 이벤트 루프 : 이벤트 루프는 콜 스택(Call Stack)이 비어 있고 실행할 코드가 없을 때, 태스크 큐 또는 마이크로태스크 큐에서 작업을 하나씩 가져와 콜 스택에 추가하고 실행합니다. 마이크로태스크 큐가 비워진 후에야 태스크 큐에서의 작업이 콜 스택으로 이동합니다.

  4. 렌더링 : 브라우저 환경에서 이벤트 루프는 렌더링 작업(화면 갱신)도 관리합니다. 브라우저는 렌더링을 위한 최적의 시점을 결정하고, 필요한 경우 렌더링을 수행합니다.

태스크 큐 / 이벤트 큐 / 콜백 큐 & 마이크로태스크 큐 Detail

테스크 큐 / 이벤트 큐 / 콜백 큐

세 용어는 종종 같은 맥락에서 사용되며, 기본적으로 같은 것을 가리킵니다. 이 큐들은 비동기 작업(예: setTimeout, setInterval, 사용자 이벤트 등)의 콜백 함수를 저장하는 대기열입니다. JavaScript 엔진이 이 큐에 있는 작업들을 순서대로 처리하게 됩니다. 이벤트 루프는 콜 스택(Call Stack)이 비어 있을 때 이 큐에 있는 작업을 콜 스택으로 이동시켜 실행합니다.

  1. 테스크 큐/이벤트 큐 : 주로 외부 비동기 이벤트(예: 마우스 클릭, 네트워크 요청 완료)에 대한 콜백을 처리하기 위해 사용됩니다.

  2. 콜백 큐 : 이름에서 알 수 있듯, 이 큐는 실행될 콜백 함수들을 저장합니다. 이 용어는 테스크 큐 또는 이벤트 큐와 동의어로 사용될 수 있습니다.

마이크로태스크 큐

마이크로태스크 큐는 테스크 큐와 별도로 존재하며, 주로 프로미스(Promises) 와 같은 더 미세한 비동기 작업의 콜백을 처리 합니다. 마이크로태스크 큐의 작업들은 테스크 큐의 작업들보다 높은 우선 순위를 가지며, 이벤트 루프는 모든 마이크로태스크가 처리될 때까지 다른 테스크(이벤트 큐의 작업)를 처리하지 않습니다. 즉, 콜 스택이 비어 있을 때 이벤트 루프는 먼저 마이크로태스크 큐를 비우고 나서야 테스크 큐에 있는 작업을 처리합니다.

  1. 마이크로태스크 큐 : Promise.then(), Promise.catch(), Promise.finally() 등 프로미스의 콜백과 MutationObserver의 콜백이 이 큐에 포함됩니다. 이 큐의 작업들은 현재 실행 중인 스크립트가 완료된 직후, 그리고 이벤트 루프가 다른 테스크를 실행하기 전에 처리됩니다.

콜 스택이란

콜 스택(Call Stack)은 프로그램에서 메소드 또는 함수의 호출을 추적하는 데이터 구조입니다.

콜 스택은 LIFO(Last In First Out) 원칙 을 따르는 스택 구조를 가지며, 함수가 호출될 때마다 해당 함수에 대한 스택 프레임이 콜 스택에 푸시(push)됩니다. 각 스택 프레임은 해당 함수의 매개변수, 지역 변수 등의 정보를 포함 합니다.

함수의 실행이 완료되면, 해당 함수에 대한 스택 프레임이 콜 스택에서 팝(pop)되어 제거됩니다. 이렇게 콜 스택은 현재 실행 중인 모든 함수를 추적하며, 어떤 함수가 다른 함수를 호출했는지, 함수가 어떤 순서로 실행되어야 하는지 등의 정보를 관리합니다.

JavaScript와 같은 단일 스레드 언어에서는 한 번에 하나의 스택 프레임만 처리 할 수 있습니다. 이는 JavaScript가 단일 콜 스택 을 사용하며, 이로 인해 JavaScript의 실행이 블로킹(blocking) 되는 경우가 있습니다. 이러한 문제를 해결하기 위해 JavaScript는 이벤트 루프, 콜백 큐 등의 비동기 처리 메커니즘을 사용합니다.

이벤트 루프의 예시

JavaScript에서 이벤트 루프의 동작을 예시로 들어 설명하겠습니다:

console.log('첫 번째');

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

Promise.resolve().then(() => {
  console.log('세 번째');
});

console.log('네 번째');

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

  1. 1.'첫 번째''네 번째' 로그는 동기적으로 콜 스택에서 실행되어 바로 출력됩니다.

  2. 2.setTimeout의 콜백은 태스크 큐에 추가됩니다.

  3. 3.Promise.resolve().then()의 콜백은 마이크로태스크 큐에 추가됩니다.

  4. 4.콜 스택이 비어있으므로, 이벤트 루프는 마이크로태스크 큐에서 '세 번째' 로그를 먼저 콜 스택으로 옮겨 실행합니다.

  5. 5.마이크로태스크 큐가 비워지면, 이벤트 루프는 태스크 큐에서 '두 번째' 로그를 콜 스택으로 옮겨 실행합니다.

이벤트 루프 덕분에 JavaScript는 비동기 작업을 효율적으로 관리 하고, 사용자 인터랙션과 같은 이벤트를 처리 하며, UI를 부드럽게 업데이트할 수 있습니다.

클로저(Closru...

Java ORM 표...