Prologue
프로그래밍에서의 변수란 데이터들을 저장하는 공간을 뜻합니다. 변수는 값 자체를 뜻하는 것이 아니라 물건들을 저장할 수 있는 작은 상자와 같이, 변경될 수 있는 값을 위한 컨테이너라고 할 수 있습니다. 자바스크립트에서도 데이터를 담기 위해서 변수를 선언해야 하고, 또한 변수를 선언하기 위해서는 변수 선언자의 사용이 필요합니다. 이번 글에서는 javascript에서 사용되는 변수 선언 var, let, const에 대해 알아보고, 각자의 특징과 차이점을 비교해보도록 하겠습니다.
var 변수 선언자
변수 선언자 var는 let과 const가 등장하기 이전까지 JavaScript의 유일한 변수 선언자였습니다. 그래서 JavaScript로 짜여진 레거시 코드들을 보면 var를 마주칠 수 밖에 없습니다. 하지만 이 var라는 변수 선언자는 문제점이 많아서 let과 const를 등장하게 했는데요. var는 어떤 특징이 있고 어떤 문제점이 있는지를 살펴보겠습니다.
재선언과 재할당
var는 재선언과 재할당이 모두 가능한 변수 선언자입니다. 이 말은 코드 작업시에 다른 사람이 선언해 놓은 변수를 실수로 덮어쓸 수도 있다는 뜻입니다. 코드로 한번 살펴보겠습니다.
var name = "kim";
var name = "lee"; // var는 중복 선언(재선언)과 재할당이 가능하다.
console.log(name); // "lee"
위 코드에서 볼 수 있듯이 var로 선언된 변수는 재선언과 재할당이 모두 가능합니다. 만약에 내가 사용하는 변수가 이미 코드상에 존재하는 변수라면 기존에 있던 변수가 소리 소문 없이 사라져버립니다. 이러한 점은 var의 매우 큰 문제점으로 여겨지고 있습니다.
호이스팅에서의 관점
자바스크립트에는 호이스팅이라는 것이 있습니다. 실행 컨텍스트 중에서도 Lexical Environment에서 현재 컨텍스트의 정보들을 수집할 때 변수들도 같이 수집을 하게 되는데 이러한 현상이 마치 변수들을 위로 끌어올리는 것 같다고 하여 호이스팅이라는 가상의 개념이 만들어졌습니다. 실행 컨텍스트와 호이스팅에 대해서 궁금하시다면 아래의 글을 참고해주세요.
관련 포스팅: 실행 컨텍스트 (Execution Context), 호이스팅, 스코프 체인
console.log(a); // undefined
var a = "hello";
위 코드에서 볼 수 있듯이 var로 선언된 변수는 호이스팅의 영향을 받아 전역 변수처럼 사용할 수 있게 됩니다. 단, 선언된 변수에 값이 할당되지 않은 상태로 변수 선언부만 위로 끌어올려져서 undefined가 뜨게 됩니다.
이처럼 var는 호이스팅의 영향을 받아서 전역 변수처럼 사용할 수 있게 되고 재선언과 재할당이 가능하다보니 JavaScript 코드상에서 예상치 못한 문제를 만들어 내곤 했습니다. 이러한 문제점을 해결하기 위해 ES6에서 let과 const라는 변수 선언자가 등장하게 되었습니다.
let 변수 선언자
Es6에서 등장한 let 변수 선언자는 var의 문제점이었던 재선언을 못하게 막아두고 재할당만 가능하게 만들었습니다. 그러므로 let을 사용하게 되면 내가 선언하려는 변수가 이미 존재한다면 에러를 발생시켜서 개발자가 실수로 변수를 덮어쓰는 일을 방지할 수 있게 되었습니다
재선언과 재할당
let a = "hello";
let a = "world"; // SyntaxError: Identifier 'a' has already been declared
위 코드를 보면 let으로 a를 재선언할 때 이미 있는 변수라고 하면서 SyntaxError가 뜨는 모습을 볼 수 있습니다. 만약에 혹시 모를 개발자의 실수를 막아주는 것입니다.
호이스팅에서의 관점
let은 var와 달리 호이스팅의 영향을 받지 않습니다. 더 정확하게 말하자면 let도 Lexical Environment의 수집 대상이긴 하지만 선언과 초기화가 동시에 이루어지는 var와는 달리 선언과 초기화가 분리되어서 동작하기 때문에 선언을 함으로써 실행 컨텍스트에 변수를 등록했지만 초기화가 이루어지지 않은 상태이기 때문에 메모리가 할당이 되지 않아 접근할 수 없어 참조 에러가 발생합니다. 결론적으로 let은 밑에서 선언을 했다고 해서 위에서 사용을 할 수는 없다는 것입니다.
console.log(a); // ReferenceError: Cannot access 'a' before initialization
let a = "hello";
이 부분에 대해서 더 정확한 정보를 얻고 싶으시다면 TDZ라는 키워드로 검색을 해보시는 것을 추천드립니다.
참고할 만한 블로그 링크: TDZ(Temporal Dead Zone)이란?
const 변수 선언자
Es6에서 등장한 const 변수 선언자는 JavaScript의 상수로써 재할당과 재선언이 전부 불가능합니다. 그러므로 const를 사용하게 되면 내가 선언하려는 변수가 이미 존재하거나 재할당을 시도하면 에러를 발생시켜서 변수의 값을 보호할 수 있습니다.
재선언과 재할당
const a = "hello";
const a = "world"; // SyntaxError: Identifier 'a' has already been declared
a = "world"; // TypeError: Assignment to constant variable.
위 코드를 보면 알 수 있듯이 const는 재선언과 재할당이 불가능합니다. const를 사용하게 되면 내가 선언하려는 변수가 이미 존재하거나 재할당을 시도하면 에러를 발생시켜서 변수의 값을 보호할 수 있습니다.
호이스팅에서의 관점
const 변수 선언자 역시 let과 동일합니다. Lexical Environment의 수집 대상이긴 하지만 선언과 초기화가 동시에 이루어지는 var와는 달리 선언과 초기화가 분리되어서 동작하기 때문에 선언을 함으로써 실행 컨텍스트에 변수를 등록했지만 초기화가 이루어지지 않은 상태이기 때문에 메모리가 할당이 되지 않아 접근할 수 없어 참조 에러가 발생합니다. 이러한 특징은 보다 안전한 코드를 작성할 수 있게 해줍니다.
정리
var, let, const는 모두 변수를 선언하기 위한 변수 선언자입니다. 하지만 각각의 변수 선언자는 다른 특징을 가지고 있습니다. var는 재선언과 재할당이 모두 가능하고 호이스팅의 영향을 받지만 let은 재선언은 불가능하고 재할당은 가능하며 호이스팅의 영향을 받지 않습니다. const는 재선언과 재할당이 모두 불가능하며 호이스팅의 영향을 받지 않습니다. 이러한 특징들을 표로 정리하면 아래와 같습니다.
var | let | const | |
---|---|---|---|
재선언 | O | X | X |
재할당 | O | O | X |
호이스팅 | O | X | X |