FE/JS

JavaScript: var, let, const

고감귤 2025. 5. 13. 11:19

자바스크립트에서 변수를 선언하는 방법은 세 가지가 있다: var, let, 그리고 const.

그런데 이 셋은 단순히 문법이 다른 게 아니다.

동작 방식 자체가 다르다.

그래서 어떤 걸 쓰느냐에 따라 버그가 생길 수도, 막을 수도 있다.

 

이번 글에서는 var, let, const스코프(Scope), 중복 선언, 호이스팅(Hoisting), 전역 객체(window) 네 가지 관점에서 비교해본다.


1. 스코프: 변수가 살아 있는 공간

var: 함수 스코프

var는 오직 함수 단위로만 스코프를 나눈다. {} 블록은 무시한다.

if (true) {
  var x = 1;
}
console.log(x); // 1 (밖에서도 접근됨)

함수 안에서 선언하면 그 함수 안에서만 유효하지만, 함수 바깥에서 {} 안에 선언하면 밖에서도 살아 있다.

 

let, const: 블록 스코프

letconst{} 블록 안에서만 살아 있다. 가장 큰 차이점이자 장점이다.

if (true) {
  let y = 2;
  const z = 3;
}
console.log(y); // ReferenceError
console.log(z); // ReferenceError

블록 단위로 스코프가 나뉘기 때문에 변수의 생명 주기를 더 명확하고 안전하게 관리할 수 있다.

 

for문에서 차이

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
} // 3, 3, 3

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
} // 0, 1, 2

왜 이런 차이가 발생할까?

  • var함수 스코프이기 때문에 for 루프가 돌더라도 같은 i를 계속 공유한다.
    루프가 끝난 시점에서의
    i = 3을 참조하게 된다.
  • let블록 스코프라서 루프가 돌 때마다 각각의 i가 새로운 스코프에서 생성된다.
    그래서
    setTimeout 콜백 안에서도 올바른 값이 유지된다.

2. 중복 선언: 같은 이름, 두 번 선언할 수 있을까?

var: 가능함 (하지만 위험함)

var a = 1;
var a = 2; // 가능

덮어쓰기도 되고, 오류도 안 난다. 이게 생각보다 위험하다.
의도치 않게 같은 이름으로 재선언해도
아무런 경고 없이 통과된다.

let, const: 불가능

let b = 1;
let b = 2; // ❌ SyntaxError

const c = 3;
const c = 4; // ❌ SyntaxError

동일한 스코프 안에서는 중복 선언 자체가 불가능하다.
이게
코드를 예측 가능하게 만든다.


3. 호이스팅: 선언이 끌어올려진다?

자바스크립트는 실행 전에 변수 선언과 함수 선언을 먼저 메모리에 올려둔다.
이를 호이스팅이라고 한다.

var: 선언만 끌어올려지고, 값은 undefined

console.log(d); // undefined
var d = 5;

실제로는 이렇게 처리된다:

var d;
console.log(d); // undefined
d = 5;

 

let, const: TDZ(일시적 사각지대)에 갇힘

console.log(e); // ❌ ReferenceError
let e = 10;

let, const도 호이스팅은 되지만, 초기화 전에 접근하면 에러가 난다. [ 그래서 더욱 안전하다 ]
이 현상을 **TDZ(Temporal Dead Zone)**이라고 부른다.


4. 전역 객체(window)에 등록되는가?

브라우저 환경에선 최상위 스코프에 선언된 변수들이 window 객체의 프로퍼티로 올라간다. 그런데 이것도 셋 다 다르다.

var: 등록된다

var f = 100;
console.log(window.f); // 100

var로 전역 선언하면 window 객체에 자동으로 붙는다.
그래서 실수로 전역 내장 객체(
alert, location 등)를 덮어쓸 위험도 있다.

let, const: 등록되지 않는다

let g = 200;
const h = 300;
console.log(window.g); // undefined
console.log(window.h); // undefined

let, const는 전역에서 선언돼도 window에 등록되지 않는다. [ 그래서 전역 오염이 훨씬 적다. ]


🔚 정리: 언제 무엇을 써야 할까?

구분 var let const
스코프 함수 블록 블록
중복 선언 가능 불가능 불가능
호이스팅 선언만(undefined) TDZ 존재 TDZ 존재
window 등록 ❌ 안 됨 ❌ 안 됨
재할당 가능 가능 가능 ❌ 불가능

 


✍️ 실무 기준 추천

  • var는 이제 쓰지 말자. 예측 불가능하고 안전하지 않다.
  • 기본은 const: 재할당이 불필요하다면 const로 선언해두는 게 실수를 줄인다.
  • 변화가 필요한 값에만 let을 쓰자.
const user = { name: 'lee' }; // ✅ 객체 내부는 바뀔 수 있음
user.name = 'kim';

let count = 0;
count += 1;

 

 

참고

https://www.youtube.com/watch?v=_zMVlKxmWHg

https://www.youtube.com/watch?v=fETYLCU2YYc