호이스팅의 개념
호이스팅(Hoisting)은 영어로 "끌어올리다"라는 뜻입니다.
쉽게 비유하자면, 선생님이 출석을 부를 때를 생각해보면 됩니다. 선생님은 수업 시작하기 전에 이미 출석부에 학생 이름이 다 적혀있어야 합니다. 수업 중간에 "어? 이 학생 이름이 없네?"라고 하면 안됩니다.
JavaScript도 마찬가지입니다. 코드를 실행하기 전에 JavaScript 엔진이 코드를 쭉 훑어보면서 "어떤 변수들과 함수들이 있는지"를 미리 파악합니다. 이때 변수와 함수 선언을 코드의 최상단으로 끌어올리는 것처럼 동작하는 게 호이스팅입니다.
정확한 정의: 변수 및 함수 선언이 스코프(유효범위)의 최상단으로 끌어올려지는 JavaScript 동작 방식
호이스팅의 의의
왜 이런게 있을까요? 호이스팅은 JavaScript의 실행 컨텍스트 생성 과정에서 자연스럽게 발생하는 현상입니다.
장점:
- 함수를 선언하기 전에 호출할 수 있어서 코드 구조를 유연하게 작성할 수 있다.
- 코드 가독성을 높일 수 있다 (메인 로직을 위에, 세부 함수들을 아래에 배치)
단점:
- 예상치 못한 버그를 만들 수 있다.
- 코드의 실행 순서가 직관적이지 않을 수 있다.
무슨 말일까요? 코드로 이해해봅시다.
// 예제 1: var 호이스팅 기본
console.log(name) // undefined (에러가 아닙니다!)
var name = '철수'
console.log(name) // '철수'
/*
위 코드는 JavaScript 엔진이 이렇게 해석합니다:
var name; // 선언부만 끌어올림
console.log(name) // undefined (선언은 됐지만 값이 아직 안 들어감)
name = '철수' // 할당은 원래 위치에서
console.log(name) // '철수'
*/
가장 쉬운 예시인데 이해가 되실까요? 다음은 함수에서의 호이스팅입니다. 함수 호이스팅은 함수 선언식과 함수 표현식에서 각각 동작하는 방식이 다릅니다.
function sum(x, y) { return x + y } -> 함수 선언식
var sum = function (x, y) { return x + y } -> 함수 표현식
// 예제 2: 함수 선언식 - 전체가 호이스팅
console.log(add(2, 3)) // 5 (작동합니다)
function add(x, y) {
return x + y
}
/*
JavaScript 엔진이 이렇게 해석합니다:
function add(x, y) {
return x + y
}
console.log(add(2, 3))
*/// 예제 3: 함수 표현식 - 변수 선언만 호이스팅
console.log(substract) // undefined
console.log(subtract(5, 2) // TypeError: subtract is not defined
var subtract = function(x, y) {
return x - y
}
/*
JavaScript 엔진이 이렇게 해석합니다:
var subtract
console.log(subtract)
console.log(subract(5, 2))
subract = function(x, y) {
return x - y
}
*/
함수 선언식에서 에러가 발생하지 않으니 더 좋아보이나요? 천만에요! 함수 표현식이 더 예측 가능하고 안전합니다. 함수는 선언 후에만 호출할 수 있다는 것이 더 직관적입니다.
다소 극단적인 예시이긴 하지만, 여러 개발자의 협업에서 왜 함수 선언식이 문제를 야기할 수 있는지 예시 코드를 살펴보겠습니다. 코드를 직접 작성하면서 로그를 살펴보면 재미있을 것입니다. 혹시 이해가 가지 않는다면 댓글 남겨주세요 :)
// 예제 4: 함수 선언식이 야기하는 호이스팅 문제
console.log(sum(3, 4));
function sum (x, y) { // 개발자 A가 선언한 sum 함수
return x + y;
}
var a = sum(1, 2);
function sum (x, y) { // 개발자 B가 선언한 sum 함수
return x + ' + ' + y + ' = ' + (x + y);
}
var c = sum(1, 2);
console.log(c)
var/let/const 에서의 호이스팅
실제 개발에서는 var을 쓰지 않죠. 자, 이제 let과 const를 알아보겠습니다. let과 const도 호이스팅이 됩니다! 하지만 var와는 다르게 동작합니다.
// 예제 5: var의 호이스팅
console.log(a) // undefined
var a = 10
console.log(a) // 10// 예제 6: let의 호이스팅
console.log(b) // ReferenceError: Cannot access 'b' before initialization
let b = 20
console.log(b) // 20// 예제 7: const의 호이스팅
console.log(c) // ReferenceError: Cannot access 'c' before initialization
const c = 30
console.log(c) // 30
"어? let과 const는 호이스팅이 안 되는 거 아니에요?"
아니에요! 호이스팅은 되는데, TDZ(Temporal Dead Zone) 때문에 접근할 수 없는 것입니다.
TDZ(Temporal Dead Zone) 이해
TDZ는 "일시적 사각지대"라는 뜻입니다.
비유하자면, 택배가 집 앞에 도착했지만(호이스팅됨) 아직 봉인 테이프가 붙어있어서 열 수 없는 상태입니다. 정해진 시간(선언문)이 되어야 테이프를 뜯고 사용할 수 있습니다.
// 예제 8: TDZ 이해하기
// TDZ 시작 (스코프 시작)
console.log('1. 스코프 시작')
// 여기는 TDZ 구간 - myName에 접근하면 에러!
// console.log(myName) // ReferenceError
let myName = '지수' // TDZ 끝! 이제 사용 가능
console.log('2. myName:', myName) // '지수'// 예제 9: TDZ를 더 명확하게 보기
function example() {
// TDZ 시작
console.log('함수 시작')
// 이 구간은 TDZ - value에 접근 불가
// console.log(value) // ReferenceError
let value = 100 // TDZ 끝
console.log(value) // 100
}
example()// 예제 10: 종합 비교
console.log('== var ==')
console.log(varVariable) // undefined (호이스팅 O, 초기화 O)
var varVariable = 'var'
console.log(varVariable) // 'var'
console.log('== let ==')
// console.log(letVariable) // ReferenceError (호이스팅 O, 초기화 X - TDZ)
let letVariable = 'let'
console.log(letVariable) // 'let'
console.log('== const ==')
// console.log(constVariable) // ReferenceError (호이스팅 O, 초기화 X - TDZ)
const constVariable = 'const'
console.log(constVariable) // 'const'
실전 문제
// 문제 1: 출력 결과는?
function test1() {
console.log(a)
console.log(b)
var a = 10
let b = 20
}
test1()// 문제 2: 출력 결과는?
var name = '전역'
function test() {
console.log(name)
var name = '지역'
console.log(name)
}
test2()'Programming Language > JavaScript' 카테고리의 다른 글
| JavaScript는 싱글스레드인데 어떻게 동시에 여러 일을 할까? (0) | 2026.02.04 |
|---|