본문 바로가기
Programming/JavaScript

[JS] 호이스팅

by 공부합시다홍아 2024. 6. 14.

이전 포스팅에서는 스코프에 대한 원리와 이해를 해보기 위해 공부를 진행하였다.
이번에는 호이스팅이란 무엇이고, 이것의 원리는 어떻게 되는 지 공부를 해보려고 한다.

 

[JS] Scope(스코프)

오늘은 JS 구문에서 스코프와 호이스팅의 개념에 대해서 공부를 해보려고 한다.평소에 프론트엔드 부분에 대한 개발을 하다보면, 우리는 아래와 같은 장애를 확인할 수 있다.Uncaught ReferenceError :

hong-study.tistory.com


먼저 호이스팅에 대한 개념을 알아보기 전에 아래와 같은 두 예시를 드며 호이스팅이란 무엇인가에 접근을 할 수 있다.

console.log(item)

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

var item = 1;

위는 각 각 let 키워드와 var 키워드로 item이 선언되기 이전에 console.log로 item을 출력했을 때이다.
순서대로, let 키워드를 사용한 경우는 Error를 만날 수 있을 것이고, var 키워드를 사용한 경우에는 undefined라는 값을 만나볼 수 있다. 이런 차이가 나는 이유가 바로 "호이스팅" 이라는 것에 있다.

호이스팅(Hoisting)

호이스팅이란 함수, 변수의 선언이 마치 위로 끌어올려진 것처럼 동작하는 것을 의미한다.
스트립트에서 이러한 동작이 발생하는 이유는 코드를 해석하고 실행하는 과정과 내부적인 변수의 선언, 할당 과정에 있다.

스크립트는 코드를 실행하기 전에 먼저 선언된 변수, 함수 등을 전역 환경에 담아두는 과정을 거친다.
그리고 이후에 정리된 코드를 실행하는 과정을 수행하게 된다.
변수 선언의 관점에서 바라보면 선언된 변수, 함수 등을 전역 환경에 담아두는 시기에 선언 단계라고 하는 과정을 거치게 된다.

그런 이유로 var 키워드의 경우는 실제로 스크립트가 구문을 이해할 때 아래와 같이 동작한다고 생각하면 된다.

var item;

console.log(item);

item = 1;

실제로는 var item = 1 이라고 아래에 명시했지만, 스크립트가 이해하는 동작과정에서는 var 키워드를 먼저 인식하여 마치 먼저 실행된 것 처럼 동작하는 이유 때문이다. 이게 더 좋은게 아닌가? 라는 말을 할 수 있지만, let 키워드나 const 키워드를 사용하게 되면, 에러를 직관적으로 만날 수 있지만, var 키워드를 사용했을 때는 직관적이지 못하고 혼동을 줄 우려가 많아 보통 let키워드나 const 키워드를 지향한다.

위에 변수의 선언 단계와 동일하게 함수도 호이스팅이라는 과정을 거치게 되는데 아래의 예시를 보며 설명을 할 수 있다.

method1();

function method1(){
	console.log(1);
}
method2();

const method2 = function() {
	console.log(1);
}

위 코드는 선언식 표기법이고, 아래 코드는 표현식 코드 표기법이다. 
출력 결과는 선언식의 경우는 "1"이라는 출력결과를 가져오지만, 표현식의 경우 method2 is not defined 라는 에러를 만나게 된다. 왜 함수 또한 위와 같은 두 결과의 차이를 낼까?

먼저 선언식의 경우 스크립트를 읽는 과정에서 위와 같이 작성을 하지만, 아래와 같이 실제로 동작한다고 보면된다.

function method1(){
	console.log(1);
}

method1();

선언식으로 작성된 코드는 읽는 과정에서 호이스팅이 되어 먼저 읽는 대상으로 간주하지만, 표현식의 경우 작성한 순서 그대로 읽어 에러를 만날 수 밖에 없다.


이제 정확한 원리에 대해서 아래에서 이해를 해보려고 한다.

변수의 선언 단계

우리가 선언하는 변수는 선언 단계, 초기화 단계, 할당 단계를 거치게 된다.

(식별자 === 변수명)

각 단계는 위와 같은 동작을 수행하게 되는데, 초기화 단계를 거치고 나면 해당 변수에 임시 메모리 공간이 할당되기 때문에 부여된 메모리는 존재하나, 값은 존재하지 않는 undefined가 담기게 된다.

초기화 단계는 자바스크립트가 실제로 코드를 실행할 때 해당 변수의 선언 코드를 만나면 수행하게 된다.
앞서 우리가 살펴본 let,const 키워드는 마치 호이스팅이 발생하지 않는 것처럼 동작했다.
하지만 사실 let과 const 또한 호이스팅이 발생한다. 자바스크립트가 실제로 코드를 실행하기 이전에 선언 단계를 거치기 떄문이다.

그 이유는 TDZ ( Temporal Dead Zone ) 때문이다. let과 const는 선언 단계와 초기화 단계가 분리되어 실행되는데, 그 사이에 TDZ가 존재한다. 초기화 단계를 거치기 전에 즉, 해당 공간에서 머무르는 변수를 참조하려 시도하면 참조 에러를 발생시키게 되는 것이다.
VAR 키워드와의 차이는 선언 단계와 초기화 단계가 거의 동시에 이루어지기 때문에 TDZ를 거치지 않아 차이가 발생하는 것이다.

즉, 변수를 변수명들이 담기는 전역 객체에 담아주는 과정과 해당 변수에 메모리 공간을 할당해주는 과정이 함께 수행하는 것이다. 선언 단계와 초기화 단계 사이에 있는 TDZ 영역이 존재하지 않게 되서 스크립트가 선언된 변수와 함수를 미리 정리하는 과정에서 이미 임시 메모리를 할당 받았기 때문에 참조 에러가 아닌 undefined를 할당 받았던 것이다. 이는 함수도 마찬가지로 동작한다. 우리가 선언한 변수에 익명함수를 할당하는 함수 표현식은 TDZ의 영향을 받기 때문에 호이스팅이 발생하는 않는 것처럼 동작하는 것이다.

728x90

'Programming > JavaScript' 카테고리의 다른 글

[JS] HTTP 란 무엇일까  (0) 2024.06.14
[JS] Scope(스코프)  (1) 2024.06.14
[JS] To do List 구현  (0) 2024.06.13
[JS] Local Storage  (2) 2024.06.13
[JS] D-DAY 카운트 구현  (0) 2024.06.13