221008 TIL 호이스팅(hoisting)이란?

금요일에 2기분들 코딩 인터뷰 때 호이스팅이라는 개념에 대한 질문이 나왔다. 사실 호이스팅이라는 단어를 난생처음 들었는데 호이스팅이 면접의 단골 질문이라고 하셨다.

호이스팅이 뭔데 단골 질문일까?? 한번 알아보자

호이스팅(hoisting)

호이스팅을 간단하게 말하면 함수가 실행되기 전에 안에 있는 변수들을 범위의 최상단으로 올리는 것을 말한다.

 

자 백날 말하는 것보다 코드 한번 쳐보는 게 이해가 훨씬 빠르니 코드를 한번 보자

var number = 1;
console.log(number);

자 위 코드에서 콘솔에 찍히는 값은 뭘까?

 

당연히 1이다. 

console.log(number);
var number = 1;

그러면 위 코드에서 콘솔에 찍히는 값은 뭘까?

undefined가 콘솔에 나오는 것을 확인할 수 있다.

?? 이게 어떻게 된 일인가 number라는 변수가 선언되기 전에 그 변수를 쓰려고 하니 당연히 number가 정의되지 않았다는 에러가 발생할 줄 알았다.

그런데 에러가 발생하지 않고 undefined가 나왔다.

 

자바에서는 변수를 선언하기 전에 그 변수를 사용하려 하면 당연히 에러가 나오는데 자바스크립트는 그렇지 않다는 것을 알 수 있다.

자바스크립트에서 위와 같은 일이 가능한 이유가 바로 호이스팅때문이다.

 

위 코드를 실행했을 때 콘솔 창에 number가 나오기 이전에 자바스크립트 엔진이 number라는 변수를 선언한 것을 확인하고 먼저 number를 저장한 다음에 console.log(number)를 실행시키기 때문에 number는 이미 정의가 되어있어 에러가 발생하지 않고 undefined가 출력된다.

 

그러면 number를 1로 선언을 했는데 1이 안 나오고 undefined가 나오는 이유는 number를 1로 할당하기 전이기 때문이다.

호이스팅할때 변수를 선언과 동시에 초기화(undefined)를 하기 때문에 초기화하기 때문이다.

 

console.log(number);
var number = 1;
console.log(number);

 

위 코드의 순서를 보면

1. 제일 먼저 자바스크립트 엔진이 선언된 변수들을 최상단으로 올린다. 즉 number라는 변수를 선언과 동시에 초기화(undefined)를 한다,

2. console.log(number)를 실행한다. 여기서 number는 아직 1을 할당하기 이전이라 undefined가 출력된다.

3. number에 1을 할당한다.

4. console.log(number)를 실행시켜 1이 나오는 것을 확인할 수 있다.

 

그러면 var로 선언한 변수만 호이스팅을 하는가??

 

아니다 let, const도 호이스팅의 대상이라서 해당 변수들을 위로 올려서 저장을 한다. 하지만 var과 달리 let, 과 const는 저장만 하지 undefined로 초기화는 하지 않는다. 

console.log(number);
let number = 1;

그래서 위 코드를 실행시키면 이제는 당연하게도 number에 접근할 수 없다는 에러가 발생한다.

let으로 선언된 number라는 변수가 호이스팅으로 메모리에 저장이 된 것까지는 사실인데 초기화되지 않은 상태로 선언만 했기 때문에 에러가 발생한다고 보면 된다.

 

number가 실제로 선언이 되고 할당이 되기 전까지는 number를 쓸 수 없는 TDZ(Temporal Dead Zone)에 빠지게 된다.

 

TDZ란

console.log(a); 
console.log(b);
var a = 1;
let b= 2;

위 코드는 아까 확인했다시피 당연히 참조 에러가 발생한다. 

b를 초기화 이전에 사용하려 했기 때문이다. 즉 let 변수는 초기화하기 전에는 읽거나 쓸 수가 없다.

 

TDZ는 시간상 사각지대라는 의미로 변수가 선언되고 변수의 초기화가 이루어지기 전까지의 구간을 말한다.

즉 위 코드에서 let b는 호이스팅으로 메모리에 저장이 되기는 했지만 초기화가 이루어지기 이전이라 TDZ에 빠졌다고 볼 수 있다.

 

마지막으로 정리를 하면 let과 const는 호이스팅이 되지 않는 것처럼 동작을 하기 때문에 호이스팅이 일어나지 않는것으로 착각하기 쉽지만 자바스크립트에서 모든 선언에서는 호이스팅이 일어난다.

 

호이스팅은 자바스크립트 문법을 처음 배울 때 배웠어야 했던 거 같은 느낌이 든다.. 그리고 호이스팅을 코딩인터뷰때 듣지 못했다면 쭉 모르다가 면접때 만나서 탈탈 털리고 눈물을 훔치면서 호이스팅을 알아보고 있을 내 모습을 생각을 하니 이제라도 배운 게 아주 다행이다

 

참조: https://developer.mozilla.org/ko/docs/Glossary/Hoisting

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#temporal_dead_zone_tdz