본문 바로가기
프로그래밍/Javascript

[JS] 변수: var, let, const

by 하나둘지금 2024. 5. 28.

변수?

자바스크립트에서 변수란 데이터를 저장하기 위해 사용되는 이름을 말한다.
변수는 메모리의 특정 위치를 가리키며, 그 위치에 저장된 값을 참조하여 프로그램 내에서 값들을 저장하고 조작할 수 있게 된다.
변수 선언과 할당을 통해 값을 저장한다.

변수의 중요한 특징 중 하나는 동적 타이핑(dynamic typing)이다. 자바스크립트는 변수의 타입을 명시적으로 지정하지 않고, 변수에 할당된 값에 따라 타입이 자동으로 결정된다. 예를 들어, 숫자 값을 변수에 할당하면 해당 변수는 숫자 타입으로 취급되며, 문자열 값을 할당하면 문자열 타입으로 취급된다.

let number = 10;  // 숫자 타입
let text = "Hello";  // 문자열 타입

동적 타이핑(dynamic typing)?

자바스크립트는 변수를 선언할 때 타입을 명시하지 않고, 할당된 값에 따라 자동으로 타입이 결정된다. 편리하지만, 잘못 사용하면 예기치 않은 오류를 발생시킬 수 있어 주의가 필요하다.

let dynamicVar;
dynamicVar = 10;  // 숫자 타입
console.log(typeof dynamicVar);  // 출력: number

dynamicVar = "Hello";  // 문자열 타입
console.log(typeof dynamicVar);  // 출력: string

dynamicVar = true;  // 불리언 타입
console.log(typeof dynamicVar);  // 출력: boolean

위의 예시에서 dynamicVar 변수는 처음에 숫자를 할당받아 숫자 타입으로 정의된다. 이후 문자열과 불리언 값을 할당받으면서 타입이 동적으로 변경된다.

타입 변환

자바스크립트는 타입 간의 자동 변환(type coercion)을 지원한다. 이는 연산 중에 필요에 따라 변수의 타입이 자동으로 변환되는 것을 의미한다. 타입 변환은 암묵적(implicit)으로 이루어질 수도 있고, 명시적(explicit)으로 개발자가 의도적으로 변환할 수도 있다.

암묵적 타입 변환

암묵적 타입 변환은 자바스크립트 엔진이 자동으로 수행하는 타입 변환이다. 예를 들어, 숫자와 문자열을 더할 때 자바스크립트는 숫자를 문자열로 변환하여 문자열 결합을 수행한다.

let result = 10 + "5";
console.log(result);  // 출력: "105"
console.log(typeof result);  // 출력: string

위의 예시에서 숫자 10과 문자열 "5"를 더하면 자바스크립트는 숫자 10을 문자열 "10"으로 변환하고, 두 문자열을 결합하여 "105"를 반환한다.

명시적 타입 변환

명시적 타입 변환은 개발자가 의도적으로 변수의 타입을 변경하는 것이다. 이를 위해 Number(), String(), Boolean()과 같은 함수를 사용할 수 있다.

let str = "123";
let num = Number(str);
console.log(num);  // 출력: 123
console.log(typeof num);  // 출력: number

let bool = Boolean(num);
console.log(bool);  // 출력: true
console.log(typeof bool);  // 출력: boolean

위의 예시에서 문자열 "123"을 Number() 함수를 사용하여 숫자 123으로 변환하고, 다시 그 숫자를 Boolean() 함수를 사용하여 불리언 값 true로 변환한다.

function add(a, b) {
    return a + b;
}

console.log(add(5, 10));  // 출력: 15 (숫자 덧셈)
console.log(add("5", 10));  // 출력: "510" (문자열 결합)
console.log(add(true, false));  // 출력: 1 (불리언 값의 숫자 변환 후 덧셈)

위의 add 함수는 두 인수를 더하는 기능을 한다. 인수의 타입에 따라 결과가 달라진다. 첫 번째 호출에서는 두 숫자를 더해 15가 출력되고, 두 번째 호출에서는 문자열 "5"와 숫자 10을 결합해 "510"이 출력된다. 세 번째 호출에서는 true가 1로, false가 0으로 변환되어 1이 출력된다.

변수는 선언 후 언제든지 다른 값을 가질 수 있으며, 변수에 저장된 값은 변경될 수 있다. 이는 변수의 가변성(mutable)을 의미한다. 예를 들어, 위의 number 변수에 새로운 값을 할당하면 변수의 값이 변경된다.

number = 20;
console.log(number);  // 출력: 20

변수의 종류

자바스크립트에서 변수를 선언하는 방법에는 var, let, const 세 가지가 있다. 각각의 키워드는 변수의 범위(scope)와 재할당 가능 여부 등에서 차이가 있다. 이러한 차이점을 이해하면 변수 선언 시 어떤 키워드를 사용할지 올바르게 선택할 수 있다.

var

var 키워드는 자바스크립트에서 가장 오래된 변수 선언 방법이다. var로 선언된 변수는 함수 범위(function scope)를 가지며, 호이스팅(hoisting)이라는 특징이 있다. 호이스팅은 변수 선언이 해당 범위의 최상단으로 끌어올려지는 현상을 말한다.

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

위의 코드에서 x 변수는 선언되기 전에 참조되었지만, 에러가 발생하지 않고 undefined 값이 출력된다. 이는 호이스팅으로 인해 x 변수가 선언된 것으로 간주되기 때문이다. 하지만 x의 초기화는 실제 코드가 실행될 때 이루어진다.

var scope = "global";
function f() {
    console.log(scope); // undefined
    var scope = "local";
    console.log(scope);
}

위의 함수는 결국 아래와 같다.

function f() {
    var scope;
    console.log(scope); // undefined
    var scope = "local";
    console.log(scope);
}

함수 유효범위(참고)

  • 블록 유효범위
    : 블록 안에 있는 코드, 즉 블록 안에 선언된 변수는 자신만의 유효범위를 가지게 되고
    블록 밖에서는 보이지 않음

  • 함수 유효범위
    : 어떤 함수안에서 선언된 모든 변수는 그 함수 전체에 걸쳐 유효하다. 변수가 미처 선언되기 전에도 유효하다.
    var의 경우, 같은 이름의 전역변수는 함수 전체에서 지역번수에 의해 감춰진다.

또한, var로 선언된 변수는 동일한 범위 내에서 다시 선언될 수 있다.

var y = 5;
var y = 10;
console.log(y);  // 출력: 10

let

let 키워드는 ES6(ECMAScript 2015)에서 도입된 변수 선언 방법이다. let으로 선언된 변수는 블록 범위(block scope)를 가지며, 이는 변수가 선언된 블록 내에서만 유효함을 의미한다. let 변수는 호이스팅되지만, 선언 전에 사용하려고 하면 참조 에러(ReferenceError)가 발생한다.

console.log(a);  // ReferenceError: a is not defined
let a = 10;
console.log(a);  // 출력: 10

또한, let으로 선언된 변수는 동일한 범위 내에서 다시 선언될 수 없다.

let b = 5;
let b = 10;  // SyntaxError: Identifier 'b' has already been declared

const

const 키워드 역시 ES6에서 도입된 변수 선언 방법이다. const로 선언된 변수는 블록 범위를 가지며, 선언과 동시에 초기화되어야 한다. 그리고 선언 이후에는 재할당이 불가능하다. 이러한 특징 때문에 const는 상수(constant)를 선언할 때 주로 사용된다.

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

const로 선언된 변수는 객체나 배열일 때, 객체의 속성이나 배열의 요소는 변경될 수 있지만, 변수 자체는 재할당할 수 없다.

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

obj = { name: "Jane" };  // TypeError: Assignment to constant variable.

let, const, var의 차이

  1. 범위(Scope):

    • var: 함수 범위(function scope)를 가지며, 함수 내에서 선언된 변수는 함수 전체에서 접근 가능하다.
    • letconst: 블록 범위(block scope)를 가지며, 변수가 선언된 블록 내에서만 접근 가능하다.
  2. 호이스팅(Hoisting):

    • var: 변수 선언이 호이스팅되지만, 초기화는 호이스팅되지 않는다. 따라서 선언 전에 변수를 참조하면 undefined가 반환된다.
    • letconst: 변수 선언이 호이스팅되지만, 선언 전에 변수를 참조하려고 하면 참조 에러(ReferenceError)가 발생한다.
  3. 재할당 가능 여부:

    • varlet: 선언 후 재할당이 가능하다.
    • const: 선언 후 재할당이 불가능하다. 단, 객체나 배열의 경우 속성이나 요소는 변경 가능하다.

예시를 통해 이러한 차이점을 명확히 살펴보자.

function varTest() {
    var x = 1;
    if (true) {
        var x = 2;  // 같은 변수
        console.log(x);  // 출력: 2
    }
    console.log(x);  // 출력: 2
}

function letTest() {
    let y = 1;
    if (true) {
        let y = 2;  // 다른 변수
        console.log(y);  // 출력: 2
    }
    console.log(y);  // 출력: 1
}

function constTest() {
    const z = 1;
    if (true) {
        const z = 2;  // 다른 변수
        console.log(z);  // 출력: 2
    }
    console.log(z);  // 출력: 1
}

varTest();
letTest();
constTest();

위의 예시에서 varTest 함수는 var로 선언된 변수가 함수 전체에서 동일하게 참조되는 반면, letTestconstTest 함수는 블록 범위를 가지므로, 블록 내에서 선언된 변수는 블록 외부의 변수와 독립적으로 존재한다.

결론은, var는 가능한 사용을 피하자. 그냥 쓰지 않는게 제일 좋다.. 변경될 수 있는 값을 저장할 때는 let을 사용하고, 한 번 할당된 후 변경되지 않는 값(상수)을 저장할 때는 const를 사용하자.