자바스크립트 실행 모델 딥다이브

호랭이·2026년 1월 7일

🏄 Web

목록 보기
4/4

이벤트 루프 - 콜스택 - 실행 컨텍스트 - 스코프까지 연결하고 이해하기

자바스크립트를 사용하면서 왜 이런 결과가 나오는지 명확히 설명하지 못하는 순간들이 반복됐다.
단순히 비동기, 호이스팅 같은 키워드를 아는 것과 실제 실행 흐름을 이해하는 것은 다르다고 느껴졌다.

그래서 자바스크립트 실행 모델 자체를 깊게 파고드는 것을 목표로 학습해봤다.
이벤트 루프, 콜스택, 실행 컨텍스트, 스코프를 각각 따로 외우는 것이 아니라
하나의 실행 흐름으로 연결해서 이해하는 데 집중했다.


1. 자바스크립트는 '실행 시점'의 언어

이번 학습에서 가장 크게 느낀 점은
자바스크립트의 많은 동작은 값이나 코드 위치가 아니라 실행 시점에 의해 결정된다는 사실이었다.

같은 코드라도

  • 언제 실행되는지
  • 그 시점에 콜스택이 어떤 상태인지
    에 따라 결과가 완전히 달라진다.

이 관점을 잡은 이후, 헷갈리던 비동기 동작들이 하나의 흐름으로 정리되기 시작했다.


2. 콜스택은 절대적인 우선순위를 가진 구조

콜스택은 단순히 함수 호출 순서를 저장하는 구조가 아니다.
자바스크립트에서 실행 여부를 결정하는 절대적인 기준이다.

  • 콜스택이 비어 있지 않으면 어떤 콜백도 실행될 수 없다.
  • 비동기 함수라고 해도 콜스택을 무시하고 실행되는 경우는 없다.

즉, 비동기는 '동시 실행'이 아니라 '실행 권한을 나중에 요청하는 구조'라는 점을 이해했다.


3. 이벤트 루프는 실행을 선택하는 관리자

이벤트 루프는 코드를 실행하는 주체가 아니다.
대신 다음 실행 대상을 선택하는 관리자 역할을 한다.

동작 순서를 명확히 정리해봤다.

  1. 콜스택이 비어 있는지 확인한다.
  2. 마이크로태스크 큐를 먼저 확인하고 전부 실행한다.
  3. 이후 매크로태스크 큐에서 하나를 가져와 실행한다.

중요한 점은
큐에 있다는 사실 자체는 실행을 보장하지 않는다는 점이었다.
실행은 오직 콜스택에 올라갔을 때만 이루어진다.


4. setTimeout(0)이 즉시 실행되지 않는 이유를 구조로 이해하기

setTimeout(fn, 0)이 즉시 실행되지 않는 이유를 단순히 '비동기니까'가 아니라 보다 구조적으로 이해하게 됐다.

  • setTimeout 호출 자체는 동기적으로 실행된다.
  • 콜백과 타이머 정보는 Web API에 등록된다.
  • 타이머 만료 후 콜백은 매크로태스크 큐로 이동한다.
  • 콜스택이 완전히 비워진 뒤에야 실행된다.

즉, setTimeout의 실행 시점은 시간이 아니라 콜스택 상태에 의해 결정된다.


5. Global Execution Context에서 모든 것이 시작된다

자바스크립트 코드는 실행되기 전에 Global Execution Context가 먼저 생성된다.

이 컨텍스트에서는 다음이 수행된다.

  • 전역 스코프가 생성된다.
  • this가 바인딩된다.
  • 변수와 함수 선언이 호이스팅된다.

중요한 점은
호이스팅은 코드 이동이 아니라 실행 컨텍스트 생성 단계의 작업이라는 사실이다.


6. var 호이스팅이 위험한 이유를 실행 단계까지 내려가서 이해하기

console.log(a)
var a = 1

이 코드에서 undefined가 출력되는 이유를 실행 단계 관점에서 이해했다.

  • 생성 단계에서 var a는 선언되고 undefined로 초기화된다.
  • 실행 단계에서 a = 1이 할당된다.
  • console.log는 할당 이전에 실행된다.

이로 인해 var는

  • 선언 전 접근이 가능
  • 의도치 않은 버그를 만들 수 있다는 점
    을 명확히 이해했다.

7. 함수 스코프와 블록 스코프의 차이를 구조로 이해하기

var는 함수 스코프

  • 함수 단위로만 스코프를 가진다.
  • if, for 블록은 스코프를 만들지 않는다.

let / const는 블록 스코프

  • {} 단위로 스코프를 가진다.
  • 반복문에서 매번 새로운 바인딩을 생성한다.

이 차이는 단순 문법 차이가 아니라 변수 생명주기와 참조 방식의 차이였다.


8. for + setTimeout 예제를 통해 실행 시점 사고를 완성

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0)
}

이 코드가 3 3 3을 출력하는 이유를 이벤트 루프 + 스코프 + 실행 시점 관점에서 분석해봤다.

핵심은 다음과 같았다.
1. var는 함수 스코프라 i가 하나만 존재한다.
2. for문은 동기 코드라 콜스택을 계속 점유한다.
3. 콜백은 실행되지 않고 큐에서 대기한다.
4. for문 종료 후 i는 3이 된다.
5. 콜백은 실행 시점의 i를 참조한다.

특히 for문의 증감식이 마지막 조건 비교 전에 한 번 더 실행된다는 점을 놓치고 있었다는 사실을 인지하면서,
2 2 2가 아닌 3 3 3인지 완전히 납득할 수 있었다.


9. 이번 딥다이브의 핵심 정리

  • 자바스크립트는 실행 시점 기반 언어이다.
  • 비동기는 실행을 보장하지 않는다.
  • 콜스택이 실행의 절대 기준이다.
  • 콜백은 값을 저장하지 않고 변수를 참조한다.
  • 많은 버그들는 실행 흐름을 머릿속에 그리지 못해서 발생했던 것 같다.

마무리

이번 학습을 통해
자바스크립트를 되는 대로 사용하는 단계에서 왜 그렇게 동작하는지 설명할 수 있는 단계로 한 단계 올라갔다고 느꼈다.

🧐 코드가 아닌 실행 모델 관점에서 먼저 사고하기

profile
삐약

0개의 댓글