
JavaScript를 처음 배울 때, 변수를 선언하는 세 가지 방법으로 var, let, const를 배우게 된다.
그리고 대부분이 값이 바뀌면 let, 바뀌지 않으면 const라 외우고 넘어간다.
그러나 실제로 let과 const가 등장한 이유는 훨씬 깊고, JS의 실행 컨텍스트, 스코프 모델, 예측 가능성과 직결되어 있다.
따라서 이번 글에서는 아래의 것들을 하나씩 정리해보고자 한다.
- var가 문제가 되었던 이유
- let과 const는 어떤 문제를 해결하고자 등장한 건지
- 스코프, 호이스팅, TDZ, 불변성 관점에서 어떻게 동작하는지
1. var의 구조적 한계
ES6 이전의 JS에는 변수 선언 방법이 사실상 하나 뿐이었다.
바로, 아래와 같이 var를 이용하여 선언하는 것이다.
var count = 1;
그러나 이 방법에는 크게 2가지 문제가 있었다.
1.1. 함수 스코프 문제
예를 들어 아래와 같은 코드를 봐보자.
function test() {
if (true) {
var x = 10;
}
console.log(x);
}
var는 블록 스코프가 아닌, 함수 스코프이기 때문에 if 블록을 벗어나서도 접근이 가능하고, 결과적으로 10이 로그에 찍히게 된다.
이러한 특징은 대규모 코드에서 변수 충돌이나 의도치 않은 재할당의 주범이 됐었다.
1.2. 호이스팅 + undefined 초기화 문제
아래와 같은 코드를 보자.
console.log(a);
var a = 10;
a라는 변수가 선언되기도 전에 로그에 찍으려 하고 있으므로 에러가 날 것 같지만, 실제론 실행 자체는 정상적으로 되어서 결과로 undefined이 로그에 찍힌다.
이는 호이스팅으로 인해 var 선언이 스코프의 최상단으로 끌어올려지고 undefined로 초기화되기 때문이다.
즉, 내부적으론 아래와 같이 처리되었다고 보면 된다.
var a;
console.log(a);
a = 10;
이러한 특징은 초보자에게 혼란을 주기 쉬우며, 실무에서는 버그를 조용히 숨겨버리는 위험한 특성이 된다.
2. let과 const
위에서 봤던 문제들을 해결하고자 ES6에서는 let과 const가 등장했다.
이것들이 등장한 이유는 변수의 유효 범위를 더욱 명확하게 하고, 실행 시점을 더 엄격하게 만들기 위해서이다.
즉, 차라리 가능한 빨리 에러를 내서 개발자가 알게 하자는 방향이라 보면 된다.
2.1. let과 const의 공통점 1: 블록 스코프
아래의 예시 코드를 직접 실행 해보면 알 수 있듯이, let과 const는 모두 블록 스코프를 갖는다.
if (true) {
let x = 10;
const y = 20;
}
console.log(x); // ReferenceError 발생
console.log(y); // ReferenceError 발생
즉, let과 const는 모두 블록 스코프여서 { } 단위로 생존한다.
for, if, while, try-catch 등은 모두 블록이니까 블록 스코프인 let과 const를 사용하면 변수의 수명과 영향 범위가 더욱 눈에 잘 들어오게 되는 것이다.
2.2. let과 const의 공통점 2: TDZ
let과 const는 선언 단계에서 스코프에 등록되지만, 초기화 이전까지는 TDZ(Temporal Dead Zone)에 놓여 접근이 금지된다는 특징이 있다.
예를 들어 아래와 같은 코드를 봐보자.
console.log(a);
let a = 10;
실제로 실행을 해보면 ReferenceError가 발생하는데, 이는 앞서 말했듯이 호이스팅이 안 돼서 발생한 게 아니다.
실제로는 아래와 같은 느낌으로 코드가 동작한다고 보면 된다.
(즉, 에러의 원인이 호이스팅이 안 돼서가 아니라 TDZ에 접근하려 하기 때문이다.)
let a;
// TDZ 시작
console.log(a); // TDZ이므로 접근이 불가능해서 ReferenceError
a = 10;
// TDZ 종료
이러한 설계의 목적은 선언되기 전에 사용하는 코드는 무조건 에러로 잡자는 것이다.
2.3. let과 const의 차이점: 재할당 가능 여부
이제 다들 알고 있는 차이점을 살펴보기 위해 아래의 예제 코드를 살펴보자.
let x = 1;
x = 2; // 가능 !!
const y = 1;
y = 2; // 불가능 !! (TypeError)
이처럼 let은 값을 재할당 할 수 있지만, const는 값을 재할당 할 수 없다.
여기서 조금만 더 깊이 살펴보면, const는 값이 변하지 않는다라는 의미가 아님에 주의해야 한다.
예를 들어 아래와 같은 코드는 에러가 발생할까?
const user = { name: "Kim" };
user.name = "Lee"; // 가능 !!
실제론 에러가 발생하지 않고, user.name을 찍어보면 "Lee"가 나오는 것을 확인할 수 있다.
이는 const가 막는 건 "재할당"이지 "객체 내부 변경 (뮤테이션)"이 아니기 때문이다 !!
'👩🏻💻 Frontend > 📌 JavaScript' 카테고리의 다른 글
| [JavaScript] 데이터 타입 (undefined, null, number, object 등) (0) | 2026.02.05 |
|---|---|
| [JavaScript] 이벤트 (addEventListener, 이벤트 버블링, 이벤트 위임 등) (0) | 2026.02.04 |
| [JavaScript] 문서 객체 선택 (0) | 2026.02.04 |
| [JavaScript] 콜백 함수 (0) | 2026.02.04 |
| [JavaScript] 배열 (let 배열 vs const 배열) (0) | 2026.02.04 |