호이스팅(Hoisting)이란, 자바스크립트 엔진이 코드를 실행하기 전, 변수나 함수의 ‘선언’ 부분을 해당 유효 범위(scope)의 최상단으로 끌어올리는 것과 같이 동작하는 방식을 의미한다.
선언(Declaration): var myVar; 와 같이 변수가 존재함을 알리는 부분이다. 이 부분이 끌어올려진다.
할당(Assignment): myVar = 10; 처럼 변수에 실제 값을 넣는 부분이다. 이 부분은 원래 위치에 남아있다.
var myVar;
console.log(myVar); // 아직 값이 할당되지 않았으므로 'undefined' 출력
myVar = 10; // 이 시점에 값이 할당됨
console.log(myVar);
호이스팅은 var, let, const, 그리고 함수 선언에 따라 모두 다르게 동작한다.
오직 선언부(var name;)만 스코프 최상단으로 끌어올려지며, undefined로 초기화된다. 값을 할당하는 부분은 원래 자리에 그대로 남아있다.
console.log(name); // 결과: undefined
// var name; (선언부가 호이스팅되어 이 위치에 온 것처럼 동작)
var name = '백승우'; // 할당은 이 위치에서 이루어짐
console.log(name); // 결과: '백승우'
let과 const로 선언된 변수도 호이스팅이 되기는 하지만, var처럼 undefined로 초기화되지 않는다. 대신, 스코프의 시작 지점부터 변수 선언문에 도달하기 전까지 ‘일시적 사각지대(Temporal Dead Zone, TDZ)’ 에 놓이게 된다. TDZ에 있는 변수에 접근하려고 하면 undefined가 아닌, 훨씬 명확한 ReferenceError가 발생한다.
console.log(job); // ReferenceError: Cannot access 'job' before initialization
// let job; 이 호이스팅되었지만, TDZ에 있기 때문에 접근할 수 없다.
let job = '백승우'; // 이 라인을 지나야 TDZ에서 벗어난다.
console.log(job); // 결과: '백승우'
TDZ는 변수가 선언되기 전에 사용하는 실수를 막아주기 때문에, 코드를 훨씬 더 안전하고 예측 가능하게 만들어 준다.
이들은 함수가 아니라 변수의 규칙을 그대로 따른다. 함수 자체가 변수에 할당되는 형태이기 때문이다. 결과적으로, 어떤 키워드(var, let, const)로 선언했는지에 따라 호이스팅 동작이 결정된다.
- var는 스코프 범위가 함수 단위이고, undefined로 초기화되는 호이스팅 방식 때문에 예기치 않은 버그를 만들 가능성이 높다.
- let과 const는 블록 스코프를 따르며, TDZ(일시적 사각지대) 때문에 선언 전에 변수에 접근하면 명확한 오류(ReferenceError)를 발생시킨다. 이는 실수를 즉시 발견하게 도와주므로 훨씬 안전하다.
- 코드를 작성할 때, 해당 스코프(함수나 블록)에서 사용할 변수들은 가급적 가장 위쪽에 모아서 선언하는 것이 좋다.