프론트엔드/JavaScript

(JavaScript) 호이스팅(Hoisting) 완벽 정리 (var, let, const, 함수)

그린티_ 2026. 2. 2. 11:31
반응형

서론

JavaScript로 코드를 짜다 보면 가끔 이상한 상황을 마주함
분명 변수를 아래에서 선언했는데 위에서 쓸 수 있거나, 함수를 선언하기 전에 호출해도 잘 동작하는 경우가 있음

처음엔 "JavaScript가 위에서 아래로 실행되는 거 아니었어?" 싶었고, 면접 준비하면서 호이스팅(Hoisting)이라는 개념이 이걸 설명한다는 걸 알게 됨

var, let, const, 함수 선언이 각각 어떻게 호이스팅되는지, 그리고 면접에서 자주 나오는 TDZ(Temporal Dead Zone)까지 정리해봄


본론

1. 호이스팅이란?

호이스팅은 변수와 함수의 선언이 코드의 최상단으로 끌어올려지는 것처럼 동작하는 현상

실제로 코드가 물리적으로 이동하는 건 아니고, JavaScript 엔진이 코드를 실행하기 전에 선언부를 먼저 메모리에 등록하는 것

console.log(greeting); // undefined (에러가 아님!)
var greeting = '안녕하세요';

JavaScript 엔진은 이 코드를 내부적으로 이렇게 처리함:

var greeting; // 선언이 최상단으로 끌어올려짐
console.log(greeting); // undefined
greeting = '안녕하세요'; // 할당은 원래 위치에서 실행
  • 선언만 끌어올려지고, 할당은 원래 위치에 남아있음
  • 그래서 undefined가 출력되는 것 (에러가 아님!)

2. var의 호이스팅

var는 호이스팅될 때 undefined로 초기화됨

console.log(name); // undefined
var name = '그린티';
console.log(name); // '그린티'

문제: var는 예상치 못한 버그를 만듦

var count = 10;

function printCount() {
  console.log(count); // undefined (10이 아님!)
  var count = 20;
  console.log(count); // 20
}

printCount();

함수 안에서 var count가 호이스팅되면서, 전역 count가 아니라 지역 count(아직 undefined)를 참조하게 됨. 이런 버그는 찾기가 정말 어려움


3. let과 const의 호이스팅 + TDZ

"let과 const는 호이스팅이 안 된다"는 말을 많이 들었는데, 사실 호이스팅은 됨. 다만 동작 방식이 다름

console.log(name); // ReferenceError: Cannot access 'name' before initialization
let name = '그린티';

varundefined가 나오는데, let은 에러가 남. 왜?

TDZ (Temporal Dead Zone)

letconst는 호이스팅되지만, 선언 위치에 도달하기 전까지는 접근할 수 없는 구간에 놓임. 이 구간을 TDZ(일시적 사각지대)라고 부름

// --- TDZ 시작 ---
// 이 구간에서 name에 접근하면 ReferenceError
console.log(name); // ❌ ReferenceError
// --- TDZ 끝 ---
let name = '그린티'; // 여기서 초기화됨
console.log(name); // ✅ '그린티'

호이스팅이 안 되는 게 아니라, 호이스팅은 되지만 초기화 전까지 접근을 막는 것

호이스팅이 된다는 증거

let x = '전역';

function test() {
  console.log(x); // ReferenceError (전역 x가 출력되지 않음!)
  let x = '지역';
}

test();

만약 let이 호이스팅이 안 됐다면 전역 x'전역'이 출력돼야 함. 하지만 에러가 나는 건, 함수 내부의 let x가 호이스팅되어 TDZ에 걸렸기 때문


4. const는 let과 뭐가 다를까?

constlet과 동일하게 호이스팅 + TDZ가 적용됨

차이점은 선언과 동시에 반드시 초기화해야 한다는 것

// ❌ SyntaxError: Missing initializer in const declaration
const name;

// ✅ 반드시 선언과 동시에 값 할당
const name = '그린티';

그리고 const재할당이 불가능

const count = 10;
count = 20; // ❌ TypeError: Assignment to constant variable

// 단, 객체/배열의 내부 값 변경은 가능!
const user = { name: '그린티' };
user.name = '녹차'; // ✅ 가능 (참조 자체는 안 변하니까)

5. 함수 호이스팅

함수는 선언 방식에 따라 호이스팅 동작이 다름

함수 선언문 — 완전히 호이스팅됨

sayHello(); // '안녕!' (선언 전인데 호출 가능!)

function sayHello() {
  console.log('안녕!');
}

함수 선언문은 선언 + 함수 본문이 통째로 호이스팅됨. 그래서 어디서든 호출 가능

함수 표현식 — 변수 호이스팅 규칙을 따름

sayHello(); // ❌ TypeError: sayHello is not a function

var sayHello = function () {
  console.log('안녕!');
};

var sayHello만 호이스팅되고 undefined로 초기화됨. undefined()를 호출한 셈이라 TypeError가 남

sayHello(); // ❌ ReferenceError: Cannot access 'sayHello' before initialization

const sayHello = function () {
  console.log('안녕!');
};

const라면 TDZ에 걸려서 ReferenceError가 남

화살표 함수도 마찬가지

greet(); // ❌ ReferenceError

const greet = () => {
  console.log('안녕!');
};

화살표 함수는 함수 표현식이므로, 변수 호이스팅 규칙(let/const → TDZ)을 따름


6. 한눈에 비교

구분 호이스팅 초기화 시점 TDZ 재선언 재할당
var 선언과 동시에 undefined ✅ 가능 ✅ 가능
let 선언문 도달 시 ❌ 불가 ✅ 가능
const 선언문 도달 시 (즉시 할당 필수) ❌ 불가 ❌ 불가
함수 선언문 ✅ (통째로) 즉시 - -
함수 표현식 변수 규칙 따름 변수 규칙 따름 변수에 따라 - -

7. 실전에서 주의할 점

코드 스타일 가이드

// ❌ 나쁜 예 — 호이스팅에 의존하는 코드
console.log(data);
var data = fetchData();

// ✅ 좋은 예 — 선언 후 사용
const data = fetchData();
console.log(data);
  • var는 쓰지 말자. letconst만 사용하면 호이스팅으로 인한 버그를 거의 방지할 수 있음
  • const를 기본으로, 재할당이 필요할 때만 let 사용
  • 변수는 사용하기 직전에 선언하는 습관을 들이자
  • 함수 선언문은 호이스팅되니까 파일 하단에 모아두는 것도 괜찮지만, 팀 컨벤션에 따르는 게 좋음

8. 면접 예상 질문 & 답변

Q1. 호이스팅이란 무엇인가요?

JavaScript 엔진이 코드를 실행하기 전에 변수와 함수의 선언을 메모리에 먼저 등록하는 동작입니다. 코드 상에서 선언이 최상단으로 끌어올려진 것처럼 동작합니다.

Q2. var, let, const의 호이스팅 차이는?

세 키워드 모두 호이스팅됩니다. var는 호이스팅 시 undefined로 초기화되지만, letconst는 초기화되지 않고 TDZ(Temporal Dead Zone)에 놓여 선언문에 도달하기 전까지 접근할 수 없습니다.

Q3. TDZ(Temporal Dead Zone)란?

letconst 변수가 호이스팅되었지만 아직 초기화되지 않은 구간입니다. 이 구간에서 변수에 접근하면 ReferenceError가 발생합니다. 변수 선언문에 도달해야 TDZ가 끝나고 접근이 가능해집니다.

Q4. 함수 선언문과 함수 표현식의 호이스팅 차이는?

함수 선언문은 함수 전체가 호이스팅되어 선언 전에 호출할 수 있습니다. 함수 표현식은 변수에 할당하는 형태이므로, 해당 변수의 호이스팅 규칙(varundefined, let/const면 TDZ)을 따릅니다.

Q5. let이 호이스팅되지 않는다고 착각하기 쉬운 이유는?

let은 TDZ 때문에 선언 전에 접근하면 에러가 발생하므로, 호이스팅이 안 되는 것처럼 보입니다. 하지만 실제로는 호이스팅이 되며, 같은 스코프 내에 let 선언이 있으면 외부 스코프의 같은 이름 변수가 가려지는 현상(shadowing)으로 이를 확인할 수 있습니다.


결론

호이스팅은 JavaScript 엔진이 코드 실행 전에 선언을 먼저 처리하는 동작

  • var: 호이스팅 + undefined로 초기화 → 버그 원인이 되기 쉬움
  • let / const: 호이스팅 + TDZ → 선언 전 접근 시 에러로 안전하게 막아줌
  • 함수 선언문: 통째로 호이스팅 → 어디서든 호출 가능
  • 함수 표현식: 변수 규칙을 따름
키워드 호이스팅 TDZ 초기화 값
var undefined
let 초기화 안 됨
const 초기화 안 됨 (즉시 할당 필수)
함수 선언문 ✅ 전체 함수 본문
함수 표현식 변수에 따라 변수에 따라 변수에 따라

실제로 프로젝트에서 var를 쓸 일은 거의 없지만, 레거시 코드를 읽거나 면접에서 동작 원리를 설명할 때 꼭 알아야 하는 개념
앞으로도 const를 기본으로, 재할당이 필요할 때만 let을 쓰는 습관을 유지해야겠음!

반응형