서론

오랫동안 var는 JavaScript에서 변수를 선언하는 유일한 방법이었습니다. ES6(ECMAScript 2015)가 도입되면서, 변수 스코프와 동작에 대한 더 많은 제어를 제공하는 letconst라는 두 개의 새로운 키워드가 추가되었습니다. 이 세 가지의 차이점을 이해하는 것은 현대적이고 유지 관리하기 쉬우며 버그 없는 JavaScript를 작성하는 데 매우 중요합니다.

이 가이드에서는 스코프, 호이스팅, 재할당 규칙을 기준으로 var, let, const를 비교합니다.

1. 스코프 (Scope)

스코프는 코드에서 변수에 접근할 수 있는 위치를 결정합니다.

var: 함수 스코프

var로 선언된 변수는 함수 스코프(function-scoped)를 가집니다. 이는 선언된 함수 내에서만 접근할 수 있음을 의미합니다. 함수 외부에서 선언되면 전역 스코프를 가집니다.

function myFunction() {
    if (true) {
        var myVar = "var로부터의 인사";
    }
    console.log(myVar); // "var로부터의 인사" - 여기서 접근 가능
}
myFunction();
// console.log(myVar); // ReferenceError: myVar is not defined - 여기서 접근 불가

myVarif 블록 밖에서도 접근 가능하다는 점에 유의하세요. 이는 var가 블록 스코프({...})를 존중하지 않기 때문이며, 예기치 않은 동작으로 이어질 수 있습니다.

letconst: 블록 스코프

letconst로 선언된 변수는 블록 스코프(block-scoped)를 가집니다. 이들은 정의된 블록(즉, 중괄호 {...} 내부) 내에서만 접근할 수 있습니다.

function anotherFunction() {
    if (true) {
        let myLet = "let으로부터의 인사";
        const myConst = "const로부터의 인사";
        console.log(myLet);   // 접근 가능
        console.log(myConst); // 접근 가능
    }
    // console.log(myLet);   // ReferenceError: myLet is not defined
    // console.log(myConst); // ReferenceError: myConst is not defined
}
anotherFunction();

이것은 훨씬 더 직관적이며 다른 많은 프로그래밍 언어에서 변수가 작동하는 방식과 유사합니다. 변수의 생명주기를 필요한 블록으로 제한하여 버그를 예방하는 데 도움이 됩니다.

2. 호이스팅 (Hoisting)

호이스팅은 코드 실행 전에 선언을 해당 스코프의 맨 위로 옮기는 JavaScript의 동작입니다.

var: 호이스팅되고 초기화됨

var 변수는 해당 스코프의 맨 위로 호이스팅되고 undefined 값으로 초기화됩니다.

console.log(hoistedVar); // undefined (오류 없음)
var hoistedVar = "나는 호이스팅되었어";
console.log(hoistedVar); // "나는 호이스팅되었어"

이는 var 변수가 선언되기 전에 접근해도 오류가 발생하지 않지만, 그 값은 undefined가 됨을 의미합니다.

letconst: 호이스팅되지만 초기화되지 않음

letconst 변수도 호이스팅되지만, 초기화되지는 않습니다. 선언 전에 접근하면 ReferenceError가 발생합니다. 블록의 시작부터 선언까지의 기간을 일시적 사각지대(Temporal Dead Zone, TDZ)라고 합니다.

// console.log(hoistedLet); // ReferenceError: Cannot access 'hoistedLet' before initialization
let hoistedLet = "나도 호이스팅되었어";

// console.log(hoistedConst); // ReferenceError: Cannot access 'hoistedConst' before initialization
const hoistedConst = "나도 그래";

이 동작은 값이 할당되기 전에 변수를 실수로 사용하는 것을 방지하여 코드를 더 견고하게 만듭니다.

3. 재할당 (Reassignment)

이것이 letconst의 주된 차이점입니다.

varlet: 재할당 가능

var 또는 let으로 선언된 변수는 업데이트하거나 재할당할 수 있습니다.

var myVarVariable = "첫 번째 값";
myVarVariable = "새로운 값"; // 허용됨

let myLetVariable = "첫 번째 값";
myLetVariable = "새로운 값"; // 허용됨

const: 재할당 불가

const(상수를 의미)로 선언된 변수는 선언 시에 초기화되어야 하며 새로운 값을 재할당할 수 없습니다.

const myConstVariable = "이 값은 상수입니다";
// myConstVariable = "변경 시도"; // TypeError: Assignment to constant variable.

객체 및 배열에 대한 중요 참고 사항: const로 객체나 배열을 선언하면, 그 내용이 아니라 해당 객체/배열에 대한 참조가 상수임을 의미합니다. 객체의 속성이나 배열의 요소는 여전히 수정할 수 있습니다.

const myObj = { name: "Alice" };
myObj.name = "Bob"; // 이것은 허용됩니다!
console.log(myObj.name); // "Bob"

const myArray = [1, 2, 3];
myArray.push(4); // 이것도 허용됩니다!
console.log(myArray); // [1, 2, 3, 4]

// 하지만 변수 자체를 재할당할 수는 없습니다
// myObj = { name: "Charlie" }; // TypeError
// myArray = [5, 6]; // TypeError

요약 및 모범 사례

키워드 스코프 호이스팅 재할당 재선언(같은 스코프 내)
var 함수 호이스팅되고 undefined로 초기화
let 블록 호이스팅되지만 초기화되지 않음(TDZ) 아니요
const 블록 호이스팅되지만 초기화되지 않음(TDZ) 아니요 아니요

현대 JavaScript 변수 선언의 모범 사례는 다음과 같습니다.

  1. 기본적으로 const 사용: 우발적인 재할당을 방지하여 코드를 더 예측 가능하게 만듭니다. 변수의 식별자가 재할당되지 않을 것임을 나타냅니다.
  2. 변수를 재할당해야 할 때만 let 사용: 이는 일반적으로 루프 카운터나 블록 내에서 업데이트해야 하는 변수에 해당합니다.
  3. var 사용 피하기: 현대 JavaScript(ES6+)에서는 var를 사용할 이유가 거의 없습니다. var의 함수 스코프 및 호이스팅 동작은 letconst가 방지하도록 설계된 버그를 유발할 수 있습니다.

이러한 규칙을 따르면 더 명확하고 신뢰할 수 있으며 디버깅하기 쉬운 JavaScript 코드를 작성할 수 있습니다.

Leave a comment