변수 선언의 정석: var를 버리고 let과 const를 쓰는 이유

자바스크립트(JavaScript)를 배우기 시작하면 가장 먼저 접하는 것이 변수 선언입니다. 과거에는 var 하나로 충분했지만, 2015년 ES6(ECMAScript 2015)가 등장하면서 let과 const라는 새로운 표준이 자리 잡았습니다.
이제 더 이상 현대적인 프로젝트에서 var를 사용하는 것은 권장되지 않습니다. 왜 var가 '나쁜 관습'이 되었는지, 그리고 let과 const가 어떻게 코드의 안정성을 높여주는지 예제를 통해 자세히 알아보겠습니다.
1. var의 치명적인 단점 3가지
① 블록 스코프(Block Scope)의 부재
var는 함수 단위로만 유효 범위가 결정되는 **함수 스코프(Function Scope)**를 가집니다. 이는 if문이나 for문 안에서 선언한 변수가 외부에서도 살아남아 예기치 못한 버그를 유발함을 의미합니다.
예제: for문에서의 변수 유출
for (var i = 0; i < 5; i++) {
// 반복문 수행
}
console.log(i); // 출력: 5 (반복문이 끝났음에도 i가 사라지지 않고 접근 가능함)
위 예제에서 i는 반복문 안에서만 쓰여야 하지만, 전역 변수처럼 남게 됩니다. 이는 대규모 프로젝트에서 변수 이름이 겹치게 만드는 주요 원인이 됩니다.
② 변수 중복 선언 허용
var는 같은 이름으로 변수를 여러 번 선언해도 에러를 발생시키지 않습니다.
예제: 의도치 않은 덮어쓰기
var user = "Kim";
console.log(user); // Kim
// ... 수백 줄의 코드가 흐른 뒤 ...
var user = "Lee"; // 에러 없이 재선언됨
console.log(user); // Lee (기존 데이터가 손실됨)
자신도 모르게 기존 변수를 덮어버릴 위험이 매우 큽니다.
③ 호이스팅(Hoisting)과 초기화 문제
var로 선언된 변수는 선언 전에도 참조할 수 있습니다. 이를 호이스팅이라고 하는데, 이때 값은 undefined로 할당됩니다.
예제: 이상한 참조
console.log(score); // 출력: undefined (에러가 나지 않음!)
var score = 100;
에러가 발생해야 할 시점에 undefined가 출력되면서 로직이 꼬일 수 있습니다.
2. let: 안전한 가변 변수
let은 var의 단점을 해결하기 위해 등장했습니다.
특징
- 블록 스코프: 중괄호 { } 내에서만 유효합니다.
- 중복 선언 금지: 같은 이름으로 다시 선언하면 에러가 발생합니다.
예제: 블록 스코프 확인
let message = "안녕";
if (true) {
let message = "반가워"; // 블록 내부에서만 유효한 별개의 변수
console.log(message); // 출력: 반가워
}
console.log(message); // 출력: 안녕 (외부 변수가 보호됨)
3. const: 바뀌지 않는 상수
const는 'Constant'의 약자로, 한 번 할당하면 재할당이 불가능한 상수를 선언할 때 사용합니다.
특징
- 재할당 불가: 값을 변경하려 하면 TypeError가 발생합니다.
- 선언과 동시에 초기화: 선언만 하고 값을 나중에 넣을 수 없습니다.
예제: 상수 보호
const API_URL = "[https://api.example.com](https://api.example.com)";
// API_URL = "[https://wrong.com](https://wrong.com)"; // Error: Assignment to constant variable.
주의: 객체와 배열에서의 const
const는 '변수 자체의 재할당'을 막는 것이지, 참조하고 있는 객체의 내부 값까지 고정하는 것은 아닙니다.
예제: 객체 내부 값 수정
const user = { name: "Alice" };
// 객체 자체를 바꾸는 것은 안 됨
// user = { name: "Bob" }; // 에러!
// 하지만 객체의 속성은 바꿀 수 있음
user.name = "Bob";
console.log(user.name); // 출력: Bob
4. 한눈에 비교하는 변수 선언 방식
특징varletconst
| 스코프 | 함수 레벨 | 블록 레벨 | 블록 레벨 |
| 재선언 | 가능 | 불가능 | 불가능 |
| 재할당 | 가능 | 가능 | 불가능 |
| 호이스팅 | 발생 (undefined) | 발생 (TDZ에 의해 에러) | 발생 (TDZ에 의해 에러) |
5. 결론: 무엇을 써야 할까?
현대 자바스크립트 프로그래밍에서는 다음과 같은 순서로 변수 선언을 고민하는 것이 정석입니다.
- 기본적으로 const를 사용합니다. 값이 바뀔 일이 없는 상수는 물론, 객체나 배열도 대부분 const로 선언하는 것이 안전합니다.
- 재할당이 필요한 경우에만 let을 사용합니다. (예: 루프 카운터, 토글 상태 등)
- var는 절대로 사용하지 않습니다.
의도치 않은 값의 변경을 막고 가독성을 높이기 위해 최대한 const를 활용하는 습관을 들여보세요. 코드의 예측 가능성이 훨씬 높아질 것입니다.