처음에는 단순히 “선언이 끌어올려진다”는 설명만 기억했는데, 실제로는 실행 컨텍스트의 생성 단계에서 메모리에 미리 등록되는 과정이라는 것을 이해하고 나니 호이스팅의 동작 원리가 훨씬 명확해졌습니다.
특히 var, let, const, 함수 선언문, 함수 표현식의 차이를 정리하면서, 앞으로 코드를 작성할 때 선언 위치와 TDZ를 더 주의 깊게 살펴야겠다고 느꼈습니다.
자바스크립트를 공부하다 보면 빠지지 않고 등장하는 키워드가 바로 실행 컨텍스트(Execution Context) 와 호이스팅(Hoisting) 입니다. 자바스크립트 코드가 실행되는 원리를 이해하는 데 핵심적인 개념이기 때문에 자세히 공부해보고 싶어 글을 정리하게 되었습니다.
실행 컨텍스트와 호이스팅이란?
실행 컨텍스트(Execution Context)는 자바스크립트 코드가 실행되는 환경 정보의 집합으로, 스코프, 변수, 함수 선언, this, 외부 참조 등이 포함됩니다. 코드가 실행되면 JS 엔진은 실행 컨텍스트를 생성하고, 이를 스택 구조(Call Stack) 로 관리합니다.
호이스팅(Hoisting)은 실행 컨텍스트 생성 단계에서 변수와 함수 선언이 먼저 메모리에 등록되기 때문에, 코드 상에서 마치 선언이 최상단으로 끌어올려진 것처럼 동작하는 현상입니다.
실행 컨텍스트와 호이스팅이 문제를 일으키는 상황
호이스팅은 의도하지 않은 값 참조를 만들어 버그를 유발할 수 있습니다.
예를 들어 var 키워드로 선언된 변수는 선언만 먼저 끌어올려지고 undefined로 초기화되므로, 초기화 전에 접근해도 에러가 아니라 undefined를 반환합니다. 이는 로직 상 오류를 감추는 원인이 될 수 있습니다. 반대로 let, const는 TDZ(Temporal Dead Zone) 덕분에 초기화 전 접근 시 ReferenceError를 발생시켜 이런 문제를 방지합니다.
특징
1. 실행 컨텍스트 생성 과정
- 생성 단계: 변수와 함수 선언을 메모리에 등록
- 실행 단계: 코드가 실제 실행되며 값이 할당되고 함수가 호출
실행 컨텍스트의 생성/실행 단계에 대해 설명해주세요
실행 컨텍스트는 생성 단계와 실행 단계로 나뉩니다.
생성 단계에서는 변수 객체, 렉시컬 환경, this 바인딩을 설정하고, 변수와 함수 선언을 메모리에 올립니다. 이때 var는 undefined로 초기화되고, let / const는 TDZ에 놓입니다. 실행 단계에서는 이 환경을 기반으로 순차적으로 실행되며 변수에 값이 할당되고 함수가 호출됩니다.
2. 호이스팅의 방식
- var: 선언만 호이스팅, 초기화는 실행 단계
- let/const: 선언은 호이스팅되지만 TDZ로 초기화 전 접근 불가
- 함수 선언문: 선언과 정의가 함께 호이스팅 → 선언 전에 호출 가능
- 함수 표현식: 변수 규칙을 따름(var는 undefined, let/const는 ReferenceError)
3. 스택 구조
- 전역 컨텍스트 → 함수 실행 시 새로운 컨텍스트가 생성 → 종료 시 스택에서 제거
사용 예시
1. 변수 호이스팅
console.log(a); // undefined
var a = 10;
console.log(b); // ReferenceError
let b = 20;
var a
- 실행 컨텍스트 생성 단계에서 var a는 선언만 먼저 메모리에 등록되고, undefined로 초기화됩니다.
- 따라서 선언 이전에 접근해도 에러가 아니라 undefined가 출력됩니다.
let b
- let은 선언 자체는 호이스팅되지만, 초기화가 실행 단계에서 이뤄지기 전까지는 TDZ(Temporal Dead Zone)에 묶여 있습니다.
- 따라서 초기화 전에 접근하면 ReferenceError가 발생합니다.
2. 함수 선언문 호이스팅
함수 선언문은 호이스팅 덕분에 코드 순서와 상관없이 호출 가능하지만, 과도하게 의존하면 가독성이 떨어질 수 있으므로 선언 위치를 명확히 두는 게 좋습니다.
greet(); // "Hello"
function greet() {
console.log("Hello");
}
- 함수 선언문은 선언과 정의(함수 본문 전체) 가 생성 단계에서 메모리에 등록됩니다.
- 따라서 greet 함수는 코드 어디서든 접근할 수 있고, 선언 전에 호출해도 정상적으로 실행됩니다.
3. 함수 표현식
sayHi(); // TypeError: sayHi is not a function
var sayHi = function() {
console.log("Hi");
};
- var sayHi는 변수 선언만 먼저 호이스팅되고, 초기값은 undefined로 세팅됩니다.
- 따라서 sayHi(); 실행 시점에는 sayHi가 아직 undefined 상태라서 함수 호출을 시도하다 TypeError가 발생합니다.
보조 개념 정리
- 스코프(Scope): 변수를 참조할 수 있는 유효 범위
- TDZ(Temporal Dead Zone): let/const로 선언된 변수가 초기화되기 전까지 접근할 수 없는 구간
- 콜 스택(Call Stack): 실행 컨텍스트가 쌓이고 제거되는 구조
더 공부해보고 싶은 내용
- 함수 실행 컨텍스트와 전역 실행 컨텍스트가 메모리 관점에서 어떻게 다른지?
- 호이스팅 과정에서 V8 엔진이 변수 환경과 렉시컬 환경을 실제로 어떻게 구분 관리하는지?
- 함수 표현식과 화살표 함수가 호이스팅 단계에서 어떻게 처리되는지?
'📚 cs' 카테고리의 다른 글
[JavaScript] this 바인딩 (0) | 2025.08.30 |
---|---|
[JavaScript] V8 엔진과 GC (Garbage Collection) (3) | 2025.08.28 |
개발자 기초 cs - API와 아키텍처 (1) | 2025.08.26 |
개발자 기초 cs - 컴퓨터 네트워크 기초 (2) | 2025.08.25 |
[JavaScript] 클로저(Closure)란? (1) | 2025.08.24 |