본문 바로가기
JavaScript & TypeScript

JavaScript 변수 선언의 모든 것: var, let, const의 차이점과 올바른 사용법

by 대박플머 2024. 10. 29.

var, let, const는 모두 자바스크립트에서 변수를 선언하는 데 사용되는 키워드입니다. 하지만 각 키워드는 서로 다른 특성과 동작 방식을 가지고 있으며, 이를 적절히 사용하는 것이 코드의 가독성과 유지 보수성에 큰 영향을 미칩니다. 이번 글에서는 var, let, const의 차이점과 그 사용 시점, 그리고 각 키워드의 장단점에 대해 자세히 알아보겠습니다.

1. var의 특징

1.1. 함수 스코프(Function Scope)

var로 선언된 변수는 함수 스코프를 따릅니다. 이는 변수가 선언된 함수 내에서만 접근 가능하다는 뜻입니다. 블록(예: if, for 등) 내부에서 var로 변수를 선언하더라도 해당 블록 외부에서 접근이 가능합니다. 예를 들어:

function example() {
  if (true) {
    var x = 10;
  }
  console.log(x); // 10
}

위 코드에서 if 블록 내부에서 선언된 변수 x는 함수 스코프를 따르기 때문에 블록 외부에서도 접근 가능합니다. 이는 때로는 의도치 않은 오류를 초래할 수 있습니다.

function processUserData() {
  var userId = 123;

  if (someCondition) {
    var userId = 456; // 기존 userId를 덮어씁니다
    // 여기서 새로운 userId로 작업을 수행합니다
  }

  // 이 지점에서 userId는 456입니다
  console.log("최종 사용자 ID:", userId);
  // 의도와 다르게 456이 출력될 수 있습니다
}

위에서의 예시가 짧은 코드여서 문제가 명확하지만, 실제 코드에서는 더 복잡해지고 길어기게 되면 놓치는 경우 위와 같은 실수가 발생할 수 있습니다.

  1. if 블록 내부에서 var userId를 다시 선언하면, 외부의 userId를 덮어쓰게 됩니다.
  2. 개발자가 if 블록 내부의 userId가 블록 스코프를 가질 것이라고 잘못 가정할 수 있습니다.
  3. if 블록 이후에 원래의 userId 값(123)을 사용하려고 했다면, 예상치 못한 결과(456)를 얻게 됩니다.

이러한 문제를 방지하기 위해 let을 사용하면 더 안전한 코드를 작성할 수 있습니다

1.2. 변수 호이스팅(Variable Hoisting)

var로 선언된 변수는 호이스팅됩니다. 호이스팅은 변수가 선언된 위치와 상관없이 해당 함수나 전역 스코프의 최상단으로 끌어올려지는 현상을 의미합니다. 하지만 변수 선언만 끌어올려지고, 값의 할당은 원래의 위치에서 이루어집니다.

console.log(x); // undefined
var x = 10;
console.log(x); // 10

위 코드에서 var로 선언된 변수 x는 실제 선언 전에 undefined 값을 가지게 됩니다. 이는 변수 호이스팅 때문입니다.
javascript를 하다보면 이 문제는 꼭 경험하는 것 같다. 분명 변수도 선언했는데 오류가 발생하는 경우가 있는데 이럴 때 호이스팅을 의심해보자.

1.3. 중복 선언 허용

var로 선언된 변수는 동일한 스코프 내에서 중복 선언이 가능합니다. 하지만 이는 코드를 복잡하게 만들고, 의도치 않은 버그를 초래할 수 있습니다.

var x = 10;
var x = 20; // 오류 없이 실행됨
console.log(x); // 20

여러번 변수를 선언하다보면 이런 문제가 발생할 수 있다. 그래서 최대한 의미를 부여하는 작명도 도움이 되지 않을까 싶다.

2. let의 특징

2.1. 블록 스코프(Block Scope)

let은 블록 스코프를 따릅니다. 이는 변수가 선언된 블록(중괄호 {}로 묶인 코드) 내에서만 접근 가능하다는 뜻입니다. if, for 등의 블록 내부에서 선언된 변수는 블록 외부에서는 접근할 수 없습니다.

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

위 코드에서 yif 블록 내에서만 유효하며, 블록 외부에서는 접근이 불가능합니다.

2.2. 변수 호이스팅

let으로 선언된 변수도 var와 마찬가지로 호이스팅됩니다. 하지만 let의 경우 일시적 사각지대(Temporal Dead Zone, TDZ)를 따릅니다. 즉, 변수가 선언되기 전까지는 해당 변수에 접근할 수 없습니다.

console.log(z); // ReferenceError: z is not defined
let z = 10;

위 코드에서는 z가 선언되기 전에 접근하려 하면 오류가 발생합니다.

2.3. 중복 선언 불가

let은 동일한 스코프 내에서 중복 선언이 불가능합니다. 이는 코드의 명확성을 높이고, 변수의 오염을 방지하는 데 유리합니다.

let a = 10;
let a = 20; // SyntaxError: Identifier 'a' has already been declared

2.4 변경 가능한 변수

let으로 선언된 변수는 재할당이 가능하다. 이는 변수의 값을 나중에 변경할 수 있음을 의미한다. 이는 프로그램의 유연성을 높이는 데 도움이 될 수 있다.

let b = 10;
b = 20; // 변경 가능
b = { name: "John" }; // 변경 가능

블록 스코프인 let은 함수 스코프인 var보다 명확하게 스코프를 구분할 수 있어 코드의 가독성을 높일 수 있고, 의도치 않은 변수 오염(?)을 방지할 수 있다. 코딩을 하는 개발자가 주의를 기울인다면 이러한 문제들이 발생하지 않을 것이라고 생각하면 오산이다. 항상 시스템은 의도한데로 동작하지 않을 수 있다는 의심(?)을 하는 것이 정신건강에 도움이 될 듯하다.

3. const의 특징

3.1. 상수(Constant)

const는 변수를 상수로 선언할 때 사용됩니다. 즉, 한 번 값을 할당하면 이후에 값을 변경할 수 없습니다. 하지만 const로 선언된 변수가 객체일 경우, 객체의 속성은 변경이 가능합니다.

const b = 10;
b = 20; // TypeError: Assignment to constant variable.

객체의 속성 변경 예:

const obj = { name: "John" };
obj.name = "Doe";
console.log(obj.name); // Doe

위 코드에서 객체의 참조는 변경할 수 없지만, 객체의 내부 속성은 변경이 가능합니다.

3.2. 블록 스코프

constlet과 마찬가지로 블록 스코프를 따릅니다. 즉, 선언된 블록 내에서만 유효합니다.

3.3. 변수 호이스팅 및 일시적 사각지대

const 역시 호이스팅되지만, 일시적 사각지대에 적용됩니다. 따라서 선언 전에 접근하려고 하면 오류가 발생합니다.

console.log(c); // ReferenceError: c is not defined
const c = 10;

3.4. 중복 선언 불가

const로 선언된 변수는 동일한 스코프 내에서 중복 선언이 불가능합니다. 또한, 선언과 동시에 값을 할당해야 하며, 나중에 값을 할당할 수 없습니다.

const d; // SyntaxError: Missing initializer in const declaration
d = 10;

4. 언제 var, let, const를 사용할까?

4.1. var의 사용 시점

letconst가 나온 이후에는 var의 사용이 권장되지 않습니다. 그 이유는 함수 스코프와 변수 호이스팅으로 인한 예측하기 어려운 동작 때문입니다. 가능한 경우 letconst를 사용하는 것이 좋습니다.

4.2. let의 사용 시점

let은 값을 변경해야 하는 변수를 선언할 때 사용합니다. 예를 들어, 루프에서 변수를 재할당해야 하는 경우 적합합니다.

for (let i = 0; i < 10; i++) {
  console.log(i);
}

4.3. const의 사용 시점

const는 값이 변하지 않는 상수나 참조가 변경되지 않는 객체를 선언할 때 사용합니다. 특히 객체나 배열을 사용하는 경우에는 const를 사용해 참조가 변하지 않도록 할 수 있습니다.

const numbers = [1, 2, 3];
numbers.push(4); // 배열의 내용은 변경 가능
console.log(numbers); // [1, 2, 3, 4]

5. 성능과 메모리 측면에서의 차이

일반적으로 var, let, const의 성능 차이는 미미하며, 대부분의 경우 성능 문제는 사용 방식보다는 코드 구조나 로직에서 비롯됩니다. 그러나 const는 값이 변하지 않음을 보장하기 때문에, 가독성 면에서 유리하며 메모리 관리 측면에서도 조금 더 효율적일 수 있습니다.

6. 결론

var, let, const는 자바스크립트에서 각각의 쓰임새가 명확히 구분됩니다. 과거에는 var가 주로 사용되었지만, 이제는 letconst를 주로 사용하는 것이 일반적입니다. 특히, 값이 변경되지 않는 변수를 선언할 때는 const를 사용하는 것이 권장되며, 변경이 필요한 경우에만 let을 사용해야 합니다. var는 가능한 한 사용을 지양하고, 최신 자바스크립트 문법을 활용하여 더 안전하고 유지 보수성이 높은 코드를 작성하는 것이 중요합니다.

7. 추가 참고 자료