본문 바로가기
자바스크립트

[자바스크립트] 이벤트 루프 (event loop)

by 세바개님 2023. 3. 7.

자바스크립트의 이벤트 루프(event loop)는 자바스크립트 엔진에서 실행되는 메커니즘으로, 비동기적인 코드를 실행하는 방식을 제어하는 역할을 합니다.

 

1. 목적

 

자바스크립트는 단일 쓰레드(single thread) 언어이기 때문에, 코드를 실행하는 순서가 중요합니다. 만약 코드가 순차적으로 실행되지 않는다면, 예측할 수 없는 결과가 발생할 수 있습니다. 하지만, 자바스크립트에서는 비동기 코드를 처리하기 위해 이벤트 루프를 사용합니다.

 

2. 이벤트 루프의 동작 방식

 

이벤트 루프는 두 가지 큐(queue)를 감시하며, 한 번에 하나의 작업만 처리합니다. 이 큐는 "콜 스택(call stack)"과 "태스크 큐(task queue)"입니다.

 

콜 스택은 현재 실행 중인 함수의 호출 스택(call stack)입니다. 자바스크립트 엔진이 코드를 실행할 때, 콜 스택에 함수를 추가하며, 함수가 실행을 마치면 스택에서 제거됩니다.

 

태스크 큐는 비동기 코드의 콜백 함수들이 대기하는 큐(queue)입니다. 비동기 코드는 실행을 시작하면, 콜백 함수는 태스크 큐에 넣어집니다.

 

이벤트 루프의 역할은 콜 스택이 비어있을 때, 태스크 큐에서 새로운 작업을 가져와 콜 스택에 추가하는 것입니다. 이것은 비동기 코드를 처리할 수 있게 합니다.

 

이벤트 루프의 동작 순서는 다음과 같습니다.

 

  1. 콜 스택에서 현재 실행 중인 함수가 없으면, 태스크 큐에서 작업을 가져와 콜 스택에 추가합니다.
  2. 콜 스택에 추가된 함수가 실행됩니다.
  3. 비동기 코드가 실행되면, 콜백 함수가 태스크 큐에 추가됩니다.
  4. 1번으로 돌아가, 콜 스택이 비어있으면 태스크 큐에서 다음 작업을 가져옵니다.

이렇게 이벤트 루프는 자바스크립트에서 비동기 코드를 처리하며, 예측 가능한 실행 순서를 유지합니다.

 

3. 예제 코드

 

console.log('start'); // 1

setTimeout(() => {
  console.log('timeout'); // 4
}, 0);

Promise.resolve().then(() => {
  console.log('promise'); // 3
});

console.log('end'); // 2

 

위 코드는 다음과 같이 실행됩니다.

 

  1. console.log('start')가 실행됩니다.
  2. console.log('end')가 실행됩니다.
  3. Promise.resolve().then(() => console.log('promise'))가 실행되며, 프로미스가 처리됩니다. console.log('promise')가 태스크 큐에 추가됩니다.
  4. setTimeout(() => console.log('timeout'), 0)가 실행되며, 타이머가 설정됩니다. console.log('timeout')가 태스크 큐에 추가됩니다.
  5. 콜 스택이 비어있으므로, 이벤트 루프가 태스크 큐에서 새 작업을 가져와 실행합니다. console.log('promise')가 실행됩니다.
  6. 콜 스택이 다시 비어있으므로, 이벤트 루프가 태스크 큐에서 다음 작업을 가져와 실행합니다. console.log('timeout')이 실행됩니다.

위 예제에서, setTimeout과 Promise는 비동기 코드로, 이벤트 루프를 통해 실행됩니다. setTimeout은 타이머를 설정하고, 콜백 함수를 태스크 큐에 추가합니다. Promise은 프로미스가 처리된 후, 콜백 함수를 태스크 큐에 추가합니다. 이벤트 루프는 이러한 비동기 코드를 실행하며, 실행 순서를 예측 가능하게 합니다.

 

4. 개발시 주의 해야할 점

 

1) 동기/비동기 코드 파악

코드에서 어떤 부분이 동기적으로 실행되는지, 어떤 부분이 비동기적으로 실행되는지 파악해야 합니다. 이벤트 루프는 비동기적으로 실행되는 코드를 처리하며, 이를 이용하여 코드의 효율성을 높일 수 있습니다.

2) 콜백 지옥 방지

콜백 함수를 계속 중첩하여 사용하면 콜백 지옥이 발생할 수 있습니다. 이를 방지하기 위해, Promise나 async/await 등을 사용하여 코드를 간결하게 작성할 수 있습니다.

3) 태스크 큐 과부하 방지

비동기 코드가 계속해서 실행되면 태스크 큐가 과부하될 수 있습니다. 이를 방지하기 위해, setTimeout이나 setInterval의 시간 간격을 적절하게 조절하거나, 큐에 적재되는 작업의 양을 줄이는 방법을 사용할 수 있습니다.

4) 메모리 누수 방지

비동기 코드에서는 참조하지 않는 메모리가 누적될 수 있습니다. 이를 방지하기 위해, 메모리 누수가 발생하는 코드를 파악하고, 적절한 메모리 관리를 수행해야 합니다.

5) 이벤트 버블링/캡처링 이해

이벤트 루프는 이벤트 버블링과 캡처링 개념을 기반으로 동작합니다. 이를 이해하고 이벤트 핸들러를 등록할 때, 이벤트 버블링과 캡처링 개념을 고려하여 작성해야 합니다.

댓글