thumbnail

호이스팅에 대해 알아보자! (feat. var, let, const 차이)

생성일2024. 10. 9.
태그
작성자Beomgu Jeon

호이스팅에 대해 알아보자! (feat. var, let, const 차이)

사전 지식

호이스팅에 대해 알아보기 전에 알아두어야 할 지식이 있다. 자바스크립트는 인터프리터 언어라는 사실이다. 그럼 인터프리터 언어가 무엇일까? 아래에서 알아보도록 하자.
 

컴파일 언어 vs 인터프리터 언어

프로그래밍 언어는 크게 컴파일 언어와 인터프리터 언어로 나누어진다. 그렇다면, 컴파일 언어는 무엇이고, 인터프리터 언어는 무엇일까?
컴파일 언어는 먼저 코드 전체를 읽고, 이 코드를 컴파일 과정을 통하여 모두 기계어로 만든 뒤 실행하는 언어이다. 반면에, 인터프리터 언어의 경우 컴파일 과정이 없고, 작성된 코드를 한 줄 씩 읽어가면서 바로 실행하는 언어이다.
아래에 간단하게 내용을 정리해두었으니 읽어보면 좋을 것이다.
 
인터프리터 언어
컴파일 언어
코드 실행
컴파일 과정으로 한 번에 기계어로 변환 후 실행
한 줄 씩 읽으면서 바이트 코드로 변환 후 실행
실행 파일 생성 여부
O
X
컴파일과 실행 단계
분리
분리 되어 있지 않음
실행 속도
상대적으로 빠름
상대적으로 느림
 

그렇다면 호이스팅이란 무엇일까?

 
MDN Web Docs 에 따르면 아래와 같이 설명하고 있다.
 
JavaScript 호이스팅은 인터프리터가 코드를 실행하기 전에 함수, 변수, 클래스 또는 임포트(import)의 선언문을 해당 범위의 맨 위로 끌어올리는 것처럼 보이는 현상을 뜻합니다. - MDN Web Docs
 
도대체 이게 무슨 말일까?
 
쉽게 말하면, 자바스크립트는 한 줄 씩 실행하기 이전에, 먼저 코드를 한 번 쭉 훑어보면서 선언문을 맨 위로 올려서 실행을 하는 것처럼 보인다는 것이다.
 
이러한 호이스팅은 크게 함수 호이스팅과 변수 호이스팅으로 나누어지게 된다. 그럼 이제부터 이 두 가지의 호이스팅을 알아보자.

함수 호이스팅

선언문은 전부 맨 위로 올려서 실행이 되는 것처럼 보이는 것이 호이스팅이다. 그렇다면 모든 함수는 호이스팅이 될까? 정답은 아니다. 함수 호이스팅은 일반 함수에서만 일어나고, 익명 함수에서는 일어나지 않는다.
 
아래의 예제를 통하여 살펴보자.
  • 일반 함수
    • 아래 예제 코드와 출력을 살펴보면, 호이스팅이 일어나서 generalFunctionTest 함수를 선언하기 전에 함수를 호출했음에도, 정상적으로 실행이 되는 것을 볼 수 있다.
    • 예제 코드
      • generalFunctionTest(); function generalFunctionTest() { console.log('General Function'); } generalFunctionTest();
       
    • 출력
      • General Function General Function
  • 익명 함수
    • 반면에, 익명 함수의 경우에는 anonymousFunctionTest 함수를 선언하기 전에 호출을 하면 호이스팅이 일어나지 않아서 Reference Error 를 반환하는 것을 볼 수 있다. 이러한 이유는 변수에 함수를 저장하기 때문인데, 밑에서 설명할 변수의 생성 3가지 단계에서 할당 과정은 호이스팅에서 일어나지 않기 때문이다.
    • 예제 코드
      • anonymousFunctionTest(); // Reference Error var anonymousFunctionTest = function () { console.log('Anonymous Function'); }; anonymousFunctionTest();
       
    • 출력
      • ReferenceError: anonymousFunctionTest is not defined
       

변수 호이스팅

 
위에서 함수 호이스팅을 살펴보았고, 이제 변수 호이스팅에 대해 알아보겠다. 그 전에, 자바스크립트에서는 변수를 생성할 때 아래의 3가지 단계를 따라서 생성하게 된다.
 
1. 선언: 변수를 실행 컨텍스트에 할당하는 과정이며, 이 변수는 스코프가 참조하는 대상이 된다.
2. 초기화: 변수를 저장하기 위한 메모리 공간을 확보한 후, 변수를 undefined 값으로 초기화한다.
3. 할당: 변수에 할당하고자 하는 값으로 할당해준다.
 
이러한 3가지 과정을 거쳐 변수가 생성되는데, 여기서 주의할 점은 초기화 과정의 경우는 어떠한 방식으로 변수를 선언했느냐에 따라 실행 시점이 달라지게 된다. var 로 선언한 경우는 선언과 초기화 과정이 동시에 일어나는 반면에, let 혹은 const 로 선언된 변수의 경우에는 선언과 초기화 과정이 별도로 일어나게 된다.
 
아래의 예제를 통해 조금 더 알아보도록 하자.
  • 예제 1 - var 를 이용한 변수 선언과 할당
    • 예제 코드
      • console.log('Before declare variable statement:', val); // undefined var val = 10; console.log('After declare variable statement:', val); // 10
       
    • 출력
      • Before declare variable statement: undefined After declare variable statement: 10
        위의 예제를 실행해보면, var 의 경우 호이스팅이 일어나면서, 그 과정에서 변수의 선언과 초기화 단계가 함께 진행된다. 이러한 이유로 var 로 선언된 변수의 경우, 변수 선언문 이전에 호출을 해도 Reference Error 가 나지 않고, 호출을 할 수 있다. 다만 할당은 일어나지 않았기 때문에 undefined 로 출력되는 것을 확인할 수 있다.
       
  • 예제 2 - let 를 이용한 변수 선언과 할당
    • 예제 코드
      • console.log('Before declare variable statement:', val); // Reference Error let val = 10; console.log('After declare variable statement:', val); // 실행 x
       
    • 출력
      • ReferenceError: Cannot access 'val' before initialization
        위의 예제를 실행해보면, Reference Error 가 발생한다는 것을 알 수 있다. 이는 let 으로 선언된 변수는 호이스팅이 똑같이 일어나지만, 이 과정에서 선언만 진행이 되고 초기화 단계가 진행이 되지 않았기 때문이다. 이러한 선언만 일어나고 초기화 단계가 일어나지 않은 변수는 TDZ(Temporal Dead Zone) 에 있다고 이야기한다.
       
      TDZ(Temporal Dead Zone): 선언 단계와 초기화 단계 사이를 의미하며, 이 단계에 있는 변수에는 접근을 할 수 없다.
       
  • 예제 3 - const 를 이용한 변수 선언과 할당
    • 예제 코드
      • console.log('Before declare variable statement:', val); // Reference Error const val = 10; console.log('After declare variable statement:', val); // 실행 x
       
    • 출력
      • ReferenceError: Cannot access 'val' before initialization
        위의 예제를 실행해보면, let 키워드를 사용하여 변수를 선언했을 때와 같이 Reference Error 가 발생한다. 이는 let 과 마찬가지로 호이스팅 과정에서 선언만 진행이 되고 초기화 단계가 진행되지 않기 때문이다. 하지만 let 키워드를 사용한 선언과 한 가지 차이가 있다. 이는 아래 예제에서 확인해보자.
       
    • let 과의 차이
      • let 키워드로 선언한 변수와의 차이점은 바로 변수의 재할당이 가능한 지이다. let 키워드로 선언한 경우 변수를 몇 번이고 재할당 할 수 있는 반면에, const 키워드로 선언한 경우, 한 번 할당한 값은 두 번 다시 변경을 할 수 없다. 아래의 예제 코드를 실행해보면 알 수 있을 것이다.
      • 예제 코드
        • const val = 10; console.log('val: ', val); // 10 val = 20; // TypeError console.log('val: ', val); // 실행 x
         
      • 출력
        • TypeError: Assignment to constant variable.

정리

자바스크립트에서 호이스팅 과정은 실제로 코드를 작성할 때 반드시 고려해야 하는 부분 중 하나이다. var 키워드로 함수 혹은 변수를 선언하는 경우 선언문 전에 호출이 가능하고, 이는 코드 작성 시 불필요한 에러를 일으킬 수 있기 때문에 필요하지 않다면, 가급적 지양하고 재할당 여부를 고려하면서 let 혹은 const 로 변수와 함수를 선언하는 습관을 들이도록 하면 좋을 것이다.