학습 자료

변수 — 값에 이름을 붙여 보관한다


Article

숫자 하나를 계산했다고 하자. 그 결과를 나중에 또 쓰려면 어딘가 적어둬야 한다. 머릿속이 아니라 프로그램 안에.

값을 담아두고 이름을 붙여 다시 꺼내 쓰는 상자. 그게 변수다.

이름을 붙인다는 것

먼저 변수 없이 코드를 써본다.

console.log(1200 * 3);
console.log(1200 * 3 * 0.1);

1200이 뭔지 알 수 없고, 값이 바뀌면 두 군데를 다 고쳐야 한다. 변수를 쓰면 이렇게 된다.

const price = 1200;
const count = 3;
const total = price * count;

console.log(total);
console.log(total * 0.1);
콘솔
  • 3600
  • 360.00000000000006

읽기 쉬워졌고, 가격이 바뀌어도 한 줄만 고치면 된다.

선언과 할당

변수를 만드는 일은 두 단계로 나뉜다.

  1. 01

    선언 (declaration)

    이름을 만든다. 아직 값은 없다.

    let name;
  2. 02

    할당 (assignment)

    만들어둔 이름에 값을 넣는다. = 는 "같다"가 아니라 "넣는다"는 뜻이다.

    name = "준호";
  3. 03

    한 번에 하기

    보통은 선언과 할당을 붙여서 쓴다.

    let name = "준호";

= 기호를 수학에서처럼 "같다"로 읽으면 곧 혼란에 빠진다. 아래 코드를 보자.

let count = 1;
count = count + 1;

console.log(count);
콘솔
  • 2

수학이라면 count = count + 1은 말이 안 된다. 하지만 자바스크립트에서 이 줄은 **"오른쪽을 계산해서 왼쪽에 넣어라"**는 명령이다. 오른쪽 count + 1이 먼저 2가 되고, 그 2count에 들어간다.

메모리 상태로 보면 이렇다.

실행 후 메모리

이름표가 붙은 상자에 값이 들어 있다

price
1200
count
2
name
"준호"

이름 짓는 규칙

변수 이름은 아무렇게나 지을 수 없다. 지켜야 하는 규칙과, 지키면 좋은 관습이 있다.

예시가능 여부이유
userName가능권장되는 형태
user_name가능동작하지만 자바스크립트에서는 덜 쓴다
_count가능밑줄과 $ 로 시작할 수 있다
1stPlace불가능숫자로 시작할 수 없다
user name불가능공백을 넣을 수 없다
let불가능예약어는 쓸 수 없다

관습적으로 자바스크립트는 카멜 케이스를 쓴다. 첫 단어는 소문자로, 이어지는 단어의 첫 글자는 대문자로 붙인다. userName, totalPrice, isLoggedIn 같은 식이다.

그리고 대소문자를 구분한다. nameName은 완전히 다른 변수다.

let, const, var

변수를 만드는 키워드가 세 개다. 왜 셋이나 되는지부터 알아야 한다.

원래는 var 하나뿐이었다. 그런데 문제가 많아서, 2015년에 나온 ES6에서 letconst가 추가됐다. 지금은 var를 쓸 이유가 거의 없다.

셋의 차이

const

기본으로 쓴다

  • 재할당 불가
  • 재선언 불가
  • 블록 스코프
  • 선언과 동시에 값을 넣어야 한다

let

값이 바뀔 때만

  • 재할당 가능
  • 재선언 불가
  • 블록 스코프
  • 값 없이 선언할 수 있다

var

쓰지 않는다

  • 재할당 가능
  • 재선언 가능 — 사고의 원인
  • 함수 스코프 — 예상을 벗어난다
  • 옛날 코드에서만 만난다

재할당

let은 값을 다시 넣을 수 있고, const는 없다.

let score = 10;
score = 20;
console.log(score);

const limit = 100;
limit = 200;
콘솔
  • 20
  • TypeError: Assignment to constant variable.

const는 "상수(constant)"의 줄임말이다. 한 번 정하면 바꾸지 않겠다는 선언이다.

재선언

같은 이름으로 변수를 또 만드는 것이다. var만 이걸 허용한다.

var user = "민수";
var user = "지영";
console.log(user);
콘솔
  • 지영

아무 경고 없이 덮어써진다. 코드가 길어지면 어딘가에서 같은 이름을 또 선언했는지 알아채기 어렵고, 값이 조용히 바뀐다.

let으로 같은 걸 하면 즉시 막아준다.

let user = "민수";
let user = "지영";
콘솔
  • SyntaxError: Identifier 'user' has already been declared

에러가 나는 쪽이 더 좋은 동작이다. 실수를 실행 전에 잡아준다.

스코프

세 번째 차이는 변수가 살아 있는 범위다. 중괄호 { } 안에서 선언한 변수가 바깥에서도 보이는지의 문제다.

if (true) {
  var a = "var 로 선언";
  let b = "let 으로 선언";
}

console.log(a);
console.log(b);
콘솔
  • var 로 선언
  • ReferenceError: b is not defined

var는 중괄호를 무시하고 바깥으로 새어나온다. letconst는 중괄호 안에 갇힌다. 후자가 훨씬 예측하기 쉽다.

그래서 뭘 써야 하나

규칙은 단순하다.

선택 순서
  1. 일단 const대부분 여기서 끝난다
  2. 값을 바꿔야 하면 let반복문 카운터 등
  3. var 는 안 쓴다옛날 코드에서 읽을 줄만 알면 된다

기본을 const로 두면 좋은 점이 있다. 이 값은 안 바뀐다는 사실이 코드에 드러난다. 나중에 코드를 읽는 사람이 그 변수를 추적하지 않아도 된다.

const 는 값을 얼려버리는 게 아니다

마지막으로 가장 많이 오해하는 부분이다.

배열이나 객체를 const로 선언하면 이런 일이 벌어진다.

const numbers = [1, 2, 3];

numbers.push(4);
console.log(numbers);

numbers = [9, 9];
콘솔
  • [1, 2, 3, 4]
  • TypeError: Assignment to constant variable.

배열에 값을 추가하는 건 된다. 하지만 numbers에 아예 새 배열을 넣는 건 막힌다.

이유는 const가 지키는 게 상자에 든 값이 아니라 상자와 이름의 연결이기 때문이다. 배열은 상자에 직접 들어 있지 않고, 상자에는 "배열이 있는 위치"만 적혀 있다.

const 가 지키는 것

위치를 적어둔 상자는 잠겼지만, 그 위치에 있는 배열은 열려 있다

limit
100
numbers
0x1a2b
[1, 2, 3, 4]

지금은 완전히 이해하지 못해도 괜찮다. 4강 자료형에서 원시 타입과 참조 타입을 구분하고 나면 이 그림이 저절로 풀린다.

정리하면

  • 변수는 값에 이름을 붙여 보관하는 상자다.
  • =는 "같다"가 아니라 "오른쪽 값을 왼쪽에 넣어라"다.
  • const를 기본으로 쓰고, 재할당이 필요할 때만 let을 쓴다. var는 쓰지 않는다.
  • const는 재할당을 막을 뿐, 배열이나 객체의 내용까지 얼리지는 않는다.

다음 강의에서는 상자에 담기는 값의 종류를 본다. 숫자, 글자, 참/거짓 그리고 헷갈리기로 유명한 nullundefined까지.

변수 — 값에 이름을 붙여 보관한다 — 디코드랩(DCODELAB)