var, let, const

1. 변수 선언 방식 변경

JavaScript는 ES6(ECMAScript 2015) 이전까지 var 키워드만으로 변수를 선언했다.

하지만 var는 다른 언어들의 변수 선언 방식과 차이가 있어 개발자들이 혼란과 불편함을 겪었다.

 

그리고 ES6에서는 let과 const라는 두 가지 새로운 변수 선언 방식이 도입되었다.

이 변화는 단순한 문법 추가가 아닌, 언어의 근본적인 개선이었다.

 

 

2. var의 주요 문제점

2.1. 함수 스코프

var로 선언된 변수는 함수 스코프(function-level scope)를 가진다.

블록 스코프가 아닌 함수 스코프는 예상치 못한 동작을 유발할 수 있다.

 

ex)

function varExample() {
  if (true) {
    var x = 10;
  }
  console.log(x); // 10 - if 블록 외부에서도 접근 가능
}

varExample();

 

위 예제에서 if 블록 내에 선언된 변수 x는 함수 전체에서 접근 가능하다.

이는 코드 블록의 의미를 약화시키고 변수의 사용 범위를 명확히 제한하기 어렵게 만든다.

 

2.2. 호이스팅 문제

var 선언은 호이스팅(Hoisting)되어 변수 선언이 스코프의 최상단으로 끌어올려진다.

그러나 초기화는 호이스팅되지 않고 선언 위치에서 이루어진다.

 

ex)

console.log(x); // undefined (에러가 아님)
var x = 5;

 

위 코드는 실제로 아래와 같이 해석된다.

var x; // 선언이 최상단으로 호이스팅됨
console.log(x); // undefined
x = 5; // 초기화는 원래 위치에 남음

 

이런 동작은 변수가 선언되기 전에 사용되는 오류를 발견하기 어렵게 만든다.

 

2.3. 재선언 허용

var는 같은 스코프 내에서 동일한 변수를 여러 번 선언할 수 있다.

 

ex)

var x = 5;
console.log(x);
var x = 10; // 에러 없이 재선언 가능

 

이는 실수로 이미 사용 중인 변수 이름을 다시 선언하여 기존 값을 덮어쓰는 버그를 만들기 쉽게 한다.

 

2.4. 전역 객체 속성

전역 스코프에서 var로 선언된 변수는 전역 객체(브라우저에서는 window)의 속성이 된다.

 

ex)

var globalVar = "I'm global";
console.log(window.globalVar); // "I'm global"

 

이는 전역 네임스페이스를 오염시키고, 의도치 않은 변수 충돌을 일으킬 수 있다.

 

2.5. 반복문에서의 문제

var를 사용한 루프 변수는 루프 외부에서도 접근 가능하다.

 

ex)

for (var i = 0; i < 3; i++) {
  // 반복문 내용
}
console.log(i); // 3 - 반복문 외부에서도 접근 가능

 

또한 클로저와 함께 사용할 때 예상치 못한 동작이 발생할 수 있다.

 

ex)

var funcs = [];
for (var i = 0; i < 3; i++) {
  funcs.push(function() {
    console.log(i);
  });
}

funcs.forEach(function(foo) {
  foo(); // 3, 3, 3을 출력 (예상은 0, 1, 2)
});

 

반복문의 마지막 값이 모든 함수에 적용되는 문제가 발생한다.

 

 

3. let의 장점

3.1. 블록 스코프

let으로 선언된 변수는 블록 스코프(block-level scope)를 가진다.

블록({ }) 내에서 선언된 변수는 해당 블록 내에서만 유효하다.

 

ex)

function letExample() {
  if (true) {
    let x = 10;
    console.log(x); // 10
  }
  console.log(x); // ReferenceError: x is not defined
}

 

이는 코드 블록의 의미를 강화하고, 변수의 사용 범위를 명확히 제한한다.

 

3.2. 호이스팅 개선

let 선언도 호이스팅되지만, 초기화 전에 변수에 접근하면 ReferenceError가 발생한다.

이를 일시적 사각지대(Temporal Dead Zone, TDZ)라고 한다.

 

ex)

console.log(x); // ReferenceError: Cannot access 'x' before initialization
let x = 5;

 

이러한 동작은 변수 선언 전 사용 오류를 명확히 잡아낼 수 있게 해준다.

 

3.3. 재선언 방지

let은 같은 스코프 내에서 동일한 변수를 재선언할 수 없다.

 

ex)

let user = "Alice";
let user = "Bob"; // SyntaxError: Identifier 'user' has already been declared

 

이는 변수 이름 충돌과 의도치 않은 재할당 문제를 방지한다.

 

3.4. 전역 객체 오염 방지

전역 스코프에서 let으로 선언된 변수는 전역 객체의 속성이 되지 않는다.

 

ex)

let globalLet = "I'm global too";
console.log(window.globalLet); // undefined

 

전역 네임스페이스 오염을 방지하고 변수 충돌 가능성을 줄인다.

 

3.5. 반복문에서의 개선

let으로 선언된 반복문 변수는 각 반복마다 새로운 바인딩이 생성된다.

 

ex)

for (let i = 0; i < 3; i++) {
  // 각 반복마다 새로운 'i'가 생성됨
}
console.log(i); // ReferenceError: i is not defined

// 클로저 예제
let funcs = [];
for (let i = 0; i < 3; i++) {
  funcs.push(function() {
    console.log(i);
  });
}

funcs.forEach(function(func) {
  func(); // 0, 1, 2 출력 (예상대로 동작)
});

 

반복문에서 클로저를 사용할 때도 예상대로 동작한다.

 

 

4. const의 장점

4.1. 블록 스코프

const도 let과 마찬가지로 블록 스코프 (block-level scope) 를 가진다.

 

ex)

function constExample() {
  if (true) {
    const x = 10;
    console.log(x); // 10
  }
  console.log(x); // ReferenceError: x is not defined
}

 

4.2. 재할당 방지

const의 가장 큰 특징은 재할당이 불가능하다는 점이다.

 

ex)

const PI = 3.14159;
PI = 3.14; // TypeError: Assignment to constant variable

 

한 번 값이 할당되면 변경할 수 없어, 코드의 안정성을 높인다.

 

4.3. 선언과 동시에 초기화 필요

const는 선언과 동시에 초기화해야 한다.

 

ex)

const MAX; // SyntaxError: Missing initializer in const declaration
const MAX = 100;

 

이는 초기화되지 않은 상수를 방지하고, 의도를 명확히 한다.

 

4.4. 객체와 배열의 특성 이해

const로 선언된 객체나 배열의 내부 속성은 변경할 수 있다.

 

ex)

const user = { name: "Alice" };
user.name = "Bob"; // 가능: 객체 자체는 같은 참조를 유지
// user = { name: "Charlie" }; // 에러: 객체 참조 자체를 변경할 수 없음

const numbers = [1, 2, 3];
numbers.push(4); // 가능: 배열 내용 수정
// numbers = [5, 6]; // 에러: 배열 참조 자체를 변경할 수 없음

 

const는 변수가 가리키는 참조 자체를 변경할 수 없게 하지만, 참조된 객체의 내용은 변경 가능하다.

 

 

5. 결론

ES6의 let과 const는 var의 여러 문제점을 해결하고, 코드의 안정성과 가독성을 크게 향상시켰다.

 

  • var의 문제점: 함수 스코프, 호이스팅 문제, 재선언 허용, 전역 객체 오염, 반복문 이슈
  • let의 장점: 블록 스코프, 호이스팅 개선, 재선언 방지, 전역 오염 방지, 반복문 개선
  • const의 장점: 블록 스코프, 재할당 방지, 의도 명확화

현대 JavaScript 개발에서는 var 대신 let과 const를 사용하는 것이 강력히 권장된다.

기본적으로 const를 사용하고, 값 변경이 필요한 경우에만 let을 사용하는 것이 좋다.

이러한 접근 방식은 버그를 줄이고, 코드의 의도를 명확히 하며, 유지보수성을 향상시킨다.

'학습 > JavaScript' 카테고리의 다른 글

JavaScript 비동기 3 : async/await  (0) 2025.04.11
JavaScript 비동기 2 : 콜백, Promise  (0) 2025.04.09
JavaScript 비동기 1 : 이벤트 기반  (0) 2025.04.09
프로토타입과 Class  (0) 2025.04.08
Javascript와 C++  (0) 2024.12.15