자바스크립트는 어떻게 작동하는가?

윤도훈·2025년 5월 9일
post-thumbnail

자바스크립트 이벤트 루프 동작원리

자바스크립트는 싱글 스레드 언어이지만 사용자 인터랙션, Ajax요청 등 다양한 비동기 작업을 논리적으로 병렬처리하는것처럼 보인다.
이 모든것은 이벤트 루프(Event Loop) 라는 시스템 덕분이다.

자바스크립트 런타임의 주요 구성 요소

자바스크립트 엔진

자바스크립트 엔진은 자바스크립트 코드를 해석하고 실행하는 프로그램이다.
다음과같은 두가지 구성 요소가 있다.

콜스택(Call Stack) : 함수 호출을 관리하는 스택 구조로, 현재 실행중인 함수와 그 호출 순서를 추적한다.

힙(Heap) : 동적으로 할당된 메모리를 저장하는 공간으로, 객체와 함수 등이 저장된다.

Web API

Web API는 브라우저나 Node.js와 같은 런타임 환경에서 제공하는 API로,
자바스크립트 엔진 외부에서 비동기 작업을 처리하고(setTimeout, 타이머 요청 등) 비동기 작업의 완료 시점을 관리한다.

콜백 큐(Callback Que)

콜백 큐는 비동기 작업이 완료된 후 실행될 콜백 함수들을 대기시키는 큐로,
setTimeout의 콜백함수나 이벤트 핸들러 같은 함수들이 큐에 들어와 FIFO구조를 실행한다.
이벤트 루프

콜백 큐에는 세가지 종류가 있다.

큐종류 대표 API 우선순위 실행시점
마이크로 테스크 큐 Promise.then, queueMicrotask 가장높음 현재 테스크 종료 직후
매크로 테스크 큐 setTimeout, setInterval 중간 마이크로 테스크 큐가 모두 실행되었을때
렌더 큐 requestAnimationFrame 낮음 브라우저 렌더 직전

이벤트루프

이벤트루프는 콜 스택이 비어 있을 때 콜백 큐에서 대기 중인 콜백 함수콜 스택으로 이동시켜 실행한다.
이러한 메커니즘을 통해 자바스크립트는 비동기 작업을 처리하면서도 싱글 스레드 환경을 유지할 수 있는것이다.

이벤트루프 동작방식

  1. 자바스크립트 코드는 Call Stack에 코드가 실행되며 함수들이 쌓임.
    이때 바로 해결할 수 있는 동기코드는 바로 실행해서 보내버림
  2. 비동기 함수(예: setTimeout, fetch 등)가 호출되면, 해당 작업은 Web API로 전달
  3. 비동기를 처리해주고 관리해주는 Web API는 비동기 작업이 완료되면, 그에 대한 콜백 함수가 테스크 큐에 추가됩니다.
    이때 테스크 큐에 들어가는 기준은 위에 보았던 표와 같다.
  4. Event Loop는 Call Stack이 비는 순간을 기다림.
  5. Call Stack이 비면, Callback Queue에서 가장 오래된 콜백을 Call Stack으로 옮겨 실행.

예시로 알아보도록 하자

console.log('1');

setTimeout(() => {
  console.log('2');     // 매크로태스크
}, 0);

Promise.resolve().then(() => {
  console.log('3');     // 마이크로태스크
});

console.log('4');

코드설명

먼저 console.log(“1”) 이 스택으로 이동한 후 실행된다.

setTimeout이 스택으로 이동하고 콜백함수가 Web API로 이동한 후 비동기 처리시 매크로 태스크 큐로 이동한다.

Promise가 실행되고 Web APIs로 이동했다가 비동기 처리시 .then()은 마이크로 테스크 큐로 이동한다.

스택에 console.log(“4”) 가 스택으로 이동하여 실행된다.

마이크로 테스크에 있는 then() 이 실행되고 마지막으로 매크로 테스크 큐에 있는 setTimeout() 이 실행된다.

실행 결과 : 1 - 4 - 3 - 2

너무 바쁘면 안좋은거 아닌가?

블로킹

JavaScript에서 어떤 작업이 끝날 때까지 다음 코드 실행이 멈추는 현상을 말한다.

블로킹의 예시

function waitSync(ms) {
  const start = Date.now();
  while (Date.now() - start < ms) {
    // 아무것도 하지 않지만, CPU는 계속 돌아갑니다
  }
}

console.log("작업 시작");
waitSync(3000); // 3초 동안 블로킹 발생
console.log("작업 완료");

이 코드를 실행하면 “작업 시작”이 출력되고, 3초 동안 멈춘 뒤 “작업 완료”가 출력된다.

이 3초 동안은 사용자 인터페이스(UI)도 멈추고, 클릭이나 입력 같은 이벤트도 무시되는데 이런 현상을 블로킹이라고한다.

해결

블로킹을 해결하기위해서 비동기 기술을 적용해야한다.

console.log("시작");

setTimeout(() => {
  console.log("3초 뒤 실행");
}, 3000);

console.log("끝");

출력

시작

3초 뒤 실행

이처럼 비동기 작업은 다른 코드 실행을 막지 않는다.
이렇게 비동기를 적절히 사용하여 블로킹을 피해보자

0개의 댓글