본문으로 건너뛰기

변수: let으로 이름 붙이기

자바스크립트 목차첫 프로그램레슨 4 / 76

목차

let은 이름을 새로 만들고, =는 오른쪽 식을 그때 한 번 계산해 값 하나를 만든 뒤 왼쪽 이름을 그 값에 붙입니다. 값에 붙인 이 이름을 변수(variable)라고 합니다.

값에 이름을 붙여 두면 같은 값을 여러 줄에서 다시 쓸 수 있고, 코드를 읽는 사람도 그 값이 무엇인지 이름으로 압니다. 그런데 =는 수학의 '같다'와 모양만 같고 하는 일은 다릅니다. 이 차이를 놓치면 대입(assignment)이 이어지는 코드에서 결과를 틀리게 예측합니다. 이 레슨에서는 규칙 2를 세웁니다.

5단계 중 1단계. 대입이 세 번 이어지는 코드입니다. 다음을 누르면 1번 줄부터 실행합니다.

1let으로 이름을 만들어 값에 붙인다

let price = 4000;은 'price는 4000이다'가 아니라 '이름 price를 만들어 4000에 붙인다'로 읽습니다. 같은 일을 '4000을 price에 대입한다'고도 말합니다.

let price = 4000;
console.log(price);
console.log('price');
실행 결과
4000
price

1번 줄에서 let이 이름 price를 새로 만들고, =가 그 이름을 값 4000에 붙입니다. 2번 줄의 console.log(price)는 이름 price가 붙은 값을 찾아 4000을 찍습니다. 3번 줄처럼 따옴표로 감싸면 이름이 아니라 글자라서, 글자 price가 그대로 찍힙니다. 그림은 이름을 둥근 이름표로, 값을 네모 칸으로 그리고 화살표로 잇습니다. 값 칸 위의 number는 그 값이 수라는 표시입니다(값의 종류는 2단원). 이름은 짧은 영어 낱말로 짓고, 대문자와 소문자는 다른 이름입니다. 옛 코드에서는 let 자리에 var를 쓰기도 하는데, 규칙이 달라 이 과목은 쓰지 않습니다.

2오른쪽을 그때 한 번 계산한다

아래 코드는 대입이 세 번 이어지고, 마지막 줄이 b를 찍습니다. 그림은 이 가운데 1~3번 줄을 실행합니다.

let a = 1;
let b = a + 1;
a = 10;
console.log(b);
실행 결과
2

대입은 두 박자로 일합니다. ① 오른쪽 식을 계산해 값 하나를 만들고, ② 왼쪽 이름을 그 값에 붙입니다.

  • 1번 줄: let이 이름 a를 만듭니다. ① 값 1이 생기고 ② a가 1에 붙습니다.
  • 2번 줄: let이 이름 b를 만듭니다. ① a + 1에서 a가 붙은 값 1을 꺼내 1 + 1로 새 값 2를 만들고 ② b가 2에 붙습니다.
  • 3번 줄: 이미 있는 이름 a라 let이 없습니다. ① 새 값 10이 생기고 ② a가 10에 다시 붙습니다. 이제 1을 가리키는 이름이 없어, 그림은 1을 점선 칸으로 남기고 '가리키는 이름 없음'이라고 적습니다(다음 레슨에서 자세히).
  • 4번 줄: 이름 b가 붙은 값 2를 찍습니다.

3번 줄에서 a가 10에 붙어도 b는 2 그대로입니다. 2번 줄은 a + 1이라는 식을 b에 저장하지 않았습니다. 그때 한 번 계산한 값 2에 b를 붙였을 뿐이고, 그 계산은 거기서 끝났습니다.

규칙 2. =는 오른쪽을 그때 한 번 계산해 값 하나를 만들고, 왼쪽 이름을 그 값에 붙입니다. let·const는 이름을 새로 만듭니다.

그래서 =의 왼쪽에는 이름이, 오른쪽에는 계산할 식이 옵니다. 두 값이 같은지는 따로 === 기호로 묻습니다(4단원). const는 다음 레슨에서 봅니다.

3같은 이름은 한 번만 만든다

let은 이름을 새로 만드는 말이라, 이미 만든 이름에 다시 쓰면 오류가 납니다.

let price = 4000;
let price = 4500;
console.log(price);
실행 결과
main.js:2let price = 4500;    ^ SyntaxError: Identifier 'price' has already been declared

설명 has already been declared⁠는 '이미 만들어졌다'는 뜻으로, 이름 price를 두 번 만들었다는 오류입니다. 문법 오류라서 1번 줄도 실행되지 않았습니다. 이미 있는 이름을 새 값에 붙일 때는 2절의 3번 줄처럼 let 없이 price = 4500;으로 씁니다. 그러면 오류 없이 4500이 찍힙니다.

예제

수학으로 읽으면 말이 안 되는 줄이 있습니다. 오류가 날지, 무엇이 찍힐지 먼저 적어 본 뒤 결과를 펼쳐 보세요.

let x = 5;
x = x + 1;
console.log(x);
실행 결과 보기
실행 결과
6

예상과 다르면 그곳이 배울 곳입니다. 2번 줄은 '같다'가 아니라 대입입니다. 오른쪽 x + 1을 먼저 계산해 5 + 1로 새 값 6을 만들고, 이름 x를 6에 붙입니다(규칙 2). 그래서 오류 없이 6이 찍힙니다.

값마다 이름을 붙여 카페 영수증 석 줄을 찍습니다. 합계는 자바스크립트가 계산합니다.

let coffee = 4000;
let latte = 4500;
let total = coffee + latte;
console.log('커피:', coffee);
console.log('라테:', latte);
console.log('합계:', total);
실행 결과
커피: 4000
라테: 4500
합계: 8500

3번 줄이 coffee와 latte가 붙은 값을 꺼내 더한 8500에 이름 total을 붙입니다. 1번 줄의 값을 바꿔 다시 실행하면, 3번 줄이 그때 붙어 있는 값으로 새로 계산합니다. 과목 끝의 할 일 앱에서도 이름 붙인 값(let count = 3;)이 화면의 '전체 3개'가 되고, 앱이 이상하면 console.log로 그 값을 찍어 봅니다.

자주 틀리는 곳

틀린 생각: let y = x + 1;은 식을 저장해 두어, 뒤에서 x가 바뀌면 y도 다시 계산된다.

수학에서 y = x + 1은 x가 바뀌면 y도 따라 바뀌는 관계라 그렇게 읽게 됩니다. 자바스크립트의 =는 대입하는 그때 한 번만 계산합니다.

let x = 5;
let y = x + 1;
x = 0;
console.log(x, y);
실행 결과
0 6

y는 2번 줄에서 계산한 값 6에 붙었습니다. 3번 줄에서 x를 0에 붙여도 y는 다시 계산되지 않습니다.

맞는 규칙: =는 오른쪽 식을 그때 한 번 계산하고, 왼쪽 이름을 그 값에 붙입니다. 식은 남지 않으니 새 값이 필요하면 대입을 다시 실행합니다(규칙 2).

틀린 생각: total = 0;처럼 =만 쓰면 이름이 새로 생긴다.

2절의 a = 10;처럼 let 없는 대입을 보았으니, 새 이름도 =만으로 만들 수 있다고 여기게 됩니다. 자바스크립트에서 이름을 만드는 것은 let입니다.

total = 0;
console.log(total);
실행 결과
main.js:1total = 0;      ^ ReferenceError: total is not defined    at main.js:1:7

let이 없는 total = 0;은 '이미 있는 이름 total을 0에 다시 붙이라'는 문장인데, 그런 이름이 없어 1번 줄에서 멈췄습니다. 아래 줄에 let total이 있는데 위에서 먼저 쓰면, 같은 ReferenceError라도 설명이 달라집니다. 설명이 Cannot access 'total' …(아직 쓸 수 없다)이면 이름을 만드는 줄을 위로 올립니다.

맞는 규칙: 이름은 let·const가 만들고, let 없는 =는 이미 있는 이름을 다시 붙입니다. 처음 쓰는 이름에는 let을 붙입니다(규칙 2).

틀린 생각: =는 양쪽을 바꿔 써도 뜻이 같다.

수학에서는 x = 4와 4 = x가 같은 말이라 그렇게 여기게 됩니다. 자바스크립트의 =는 왼쪽 이름을 오른쪽 값에 붙이는 일이라 방향이 있습니다.

let price = 3500;
4000 = price;
console.log(price);
실행 결과
main.js:24000 = price;^^^^ SyntaxError: Invalid left-hand side in assignment

Invalid left-hand side⁠는 '왼쪽이 잘못되었다'는 뜻입니다. 4000처럼 코드에 바로 쓴 값은 =의 왼쪽, 곧 이름 자리에 올 수 없습니다.

맞는 규칙: =는 오른쪽 값에 왼쪽 이름을 붙이므로, 이름은 늘 =의 왼쪽에 씁니다. 4000 = price;는 price = 4000;으로 고칩니다(규칙 2).

확인 문제

1. 2절 코드의 1번 줄을 let a = 5;로 바꿨습니다. 무엇이 찍힐까요?

let a = 5;
let b = a + 1;
a = 10;
console.log(b);
힌트

2번 줄이 계산할 때 a가 붙어 있는 값을 봅니다(규칙 2).

정답
실행 결과
6

2번 줄을 실행할 때 a는 5에 붙어 있어 5 + 1 = 6에 b가 붙습니다. 3번 줄은 a만 10에 다시 붙입니다. 흔한 오답은 11입니다. 4번 줄에서 b가 a + 1을 다시 계산한다고 본 것, 곧 식이 저장된다는 생각입니다.

2. 합계가 오류 없이 찍히도록 ㉠~㉣을 위에서 아래로 놓으세요. 실행 결과는 합계 8500입니다.

  • ㉠ console.log('합계', total);
  • ㉡ let latte = 4500;
  • ㉢ let total = coffee + latte;
  • ㉣ let coffee = 4000;

놓은 뒤에는 이것도 고르세요. ㉢이 ㉠보다 위에 와야 하는 까닭은 무엇일까요?

  • ① 이름 total을 만들어 값에 붙인 뒤에야 읽을 수 있기 때문
  • ② 자바스크립트가 '합계'라는 글자를 보고 계산부터 하기 때문
  • ③ total이 coffee + latte라는 식을 기억해 두었다가 찍을 때 계산하기 때문
힌트

줄마다 = 오른쪽에서 읽는 이름과 왼쪽에 붙이는 이름을 나눠 적어 봅니다.

정답

㉣ ㉡ ㉢ ㉠ 차례이고, 까닭은 ①입니다. ㉣과 ㉡은 서로 바꿔도 됩니다. 둘 다 ㉢보다 위에만 있으면 됩니다.

  • ② 자바스크립트는 '합계'라는 글자의 뜻을 모릅니다. 쓴 차례대로 실행합니다(규칙 6).
  • ③ 식이 저장된다는 생각입니다. ㉢을 실행하는 그때 한 번 계산해 8500에 total을 붙입니다(규칙 2).

3. 두 과목 점수의 합을 찍으려다 오류가 났습니다. 이름을 처음 잘못 만든 곳은 몇 번 줄이고, 그 줄을 어떻게 고쳐야 할까요?

let korean = 90;
let englsh = 85;
let total = korean + english;
console.log(total);
실행 결과
main.js:3let total = korean + english;                     ^ ReferenceError: english is not defined    at main.js:3:22
힌트

…Error: 줄이 말하는 이름 english가 코드의 어느 줄에서 만들어졌는지 찾아봅니다.

정답

2번 줄입니다. englsh를 english로 고칩니다.

let korean = 90;
let english = 85;
let total = korean + english;
console.log(total);
실행 결과
175

오류는 3번 줄에서 났지만 이름을 잘못 만든 곳은 2번 줄입니다. 3번 줄의 english를 englsh로 바꿔도 175가 찍히지만, 철자가 틀린 이름이 남아 뒤에서 english를 쓰면 같은 오류가 다시 납니다. 흔한 오답은 3번 줄입니다. ^가 가리키는 곳이 곧 잘못 쓴 곳이라고 본 것입니다. ^는 문제를 발견한 곳입니다.

컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요. 2절 코드(네 줄)를 저장해 돌립니다. 그다음 3번 줄 a = 10;을 2번 줄 앞으로 옮기면 무엇이 찍힐지 먼저 적고, 바꿔 돌려서 맞춰 봅니다. 저장하고 돌리는 법은 내 컴퓨터에서 돌려 보기에 있습니다.

더 보기: 이름표 다시 붙이기와 const

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

자바스크립트 목차로