본문으로 바로가기

[JavaScript] var, let, const 차이, hosting, TDZ

JavaScript를 최근에 배우신 분들은 var를 모를 것입니다. 제가 처음 배울 때만 해도 var는 쓰지 말고 let, const만 써라 라고 배웠습니다. 왜 var는 사용하지 말라고 하는 것일까요? 사용하지 말라고 하는 사람들은 왜 쓰지 말아야 하는 것을 알고 있을까요? 아마 모르는 사람들이 많을 것으로 예상됩니다. 사실 사용하면 안되는 것은 아닙니다. 정확히 모르고 사용하면 예기치 못 한 문제가 발생할 수 있기 때문에 그걸 사전에 차단하기 위해 사용하지 말라는 것이죠. 이번 게시글에서는 var, let, const의 차이와 hosting, TDZ (temporal dead zone)에 대해 알아보겠습니다.

var, let, const, hosting, TDZ

var, let에 대해 먼저 알아보겠습니다. 2개는 변수를 선언할 때 사용합니다. 이 점을 동일합니다. 그런데 왜 var를 사용하지 말라고 하는 것일까요? var는 같은 변수를 여러 번 선언을 할 수 있습니다. 무슨 말인가 싶으시죠? 아래 2개의 코드를 확인해보겠습니다.

var name = "첫번째";
console.log("name", name)

var name = "두번째";
console.log("name", name)

우선 var로 작성한 코드입니다. name을 2번 선언과 동시에 초기화를 하였죠. 위 코드는 실행이 될까요? 네. 잘 실행이 됩니다. 아래 결과를 확인해보겠습니다.

그렇다면 var만 let으로 변경해보겠습니다.

let name = "첫번째";
console.log("name", name)

let name = "두번째";
console.log("name", name)

위 결과는 어떻게 될까요? 이것을 name이 2번 선언되어 실행이 되지 않습니다.

위에서 확인할 수 있듯이 var는 여러 번 선언이 가능하지만 let은 1번만 선언이 가능합니다. 또한 var는 선언하기 전에 사용할 수 있습니다. 아래 예시 코드를 확인해보겠습니다.

console.log(name);
var name = "첫번째";
console.log(name);

1번째 console은 undefined 값이 출력이 되며 var 변수에 값이 할당이 된 후 2번째 console에서는 값이 출력이 됩니다. 왜 그럴까요? 왜냐하면 var는 사실 아래와 같이 동작합니다. 코드 최상단으로 선언 부분이 이동한 것처럼 동작합니다.

var name;
console.log(name);
name = "첫번째";
console.log(name);

이제 위 동작이 이해가 되셨을 것입니다. 이러한 것을 호이스팅(hosting)이라고 합니다. 그럼 let은 어떠할까요?

console.log(name);
let name = "첫번째";
console.log(name);

let은 동작하지 않습니다. 왜 그럴까요? let은 hosting이 되지 않아서 그럴까요? 아닙니다. 사실 let도 hosting이 되지만 추가적인 개념이 있습니다. TDZ 개념과 변수 선언 단계(이후 나옴)이 추가됩니다. let과 const는 TDZ에서는 사용이 불가능합니다. 즉 초기화 (메모리 확보 및 undefined로 값 할당)하기 전에는 사용 가능하지 않습니다. 아래 이미지를 확인해봅시다.

변수는 생성 시 선언 -> 초기화 -> 할당 3가지 단계를 거치게 됩니다. var의 경우 선언, 초기화 단계가 동시에 일어나게 됩니다. 따라서 scope에 해당 변수를 등록하고 메모리 확보 후 undefined 초기화까지 하는 것이죠. 따라서 선언하기 전에 접근을 하여도 scope에는 존재하기 때문에 undefined 값이 나오게 되는 것입니다. 그러나 let의 경우 선언과 초기화 단계가 분리되어 있습니다. 선언 시 scope에 등록은 하지만 초기화는 아직 거치지 않았기 때문에 변수에 접근하여도 값이 없어 error가 발생하는 것입니다. 이 구간 즉, cope 시작부터 초기화 완료 시점까지의 구간을 TDZ (temporal dead zone) 시간상 사각지대라고 합니다. 그럼 마지막으로 const는 어떻게 되어 있을까요? const는 상수로 생성 후 값을 변경하지 못 합니다. 따라서 선언, 초기화, 할당 3가지 단계가 동시에 일어나게 됩니다. 그렇다면 결과적으로 TDZ에 접근할 수 있는 변수는 var 변수 밖에 없고 접근을 하여도 undefined 값이 있게 됩니다. 이해가 되셨나요? 그럼 아래 코드의 결과를 유추해봅시다.

let name = "첫번째";

function displayName() {
  console.log(name);
  let name = "두번째";
}

displayName();

결과를 어떻게 유추하셨나요? 첫번째가 출력될 것으로 생각하셨나요? 바로 위에서 말씀드렸지만 let 변수도 hosting이 됩니다. 그리고 이것은 scope 단위로 발생합니다. 따라서 아래와 같은 에러가 발생합니다.

그런데 여기서 말하는 scope의 기준이 어떻게 되느냐? 이것도 변수마다 다릅니다. var의 경우 function scope로 함수 단위로 scope이 이루어져있고, let, const의 경우 block scope으로 block 단위로 이루어져있습니다. 그래서 var의 경우 아래 코드가 정상 동작하게 됩니다.

function displayName() {
  if (true) {
var name = "첫번째";
  }
  console.log(name);
}

displayName();

정리

var, let, const 모두 hosting이 일어난다.

var는 function scope 단위, let, const는 block scopelet, const는 block scope 단위로 일어난다.

변수 생성은 3가지 단계로 이루어져 있으며 var, let, const가 변수를 만드는 방식에 따라 TDZ에 접근이 가능, 불가능이 정해진다.

그냥 값이 변한다 let, 안변한다 const를 사용하자.

참고자료

마지막

해당 내용은 틀릴 수도 있다는 것을 감안하여 봐주세요. 틀린 내용 및 오탈자 수정 요청 환영입니다.

반응형