본문으로 건너뛰기

합 모으기와 세기

자바스크립트 목차반복레슨 22 / 76

목차

합 모으기는 이름 하나를 0에 붙여 두고, 반복이 바퀴마다 내주는 값을 그 이름에 더해 가는 틀입니다. 세기는 조건이 맞을 때마다 1을 더하는 같은 틀입니다.

1부터 100까지의 합을 1 + 2 + …로 쓰면 식이 너무 길고, 범위가 바뀔 때마다 식을 다시 써야 합니다. 반복과 이름 하나로 쓰면 범위만 바꿔 같은 코드를 씁니다. 이 레슨은 풀이 예제를 하는 일 셋으로 나눠 읽고, 빈칸을 채우며 이 틀을 직접 쓰는 데까지 갑니다.

15단계 중 1단계. 합을 구하는 코드를 하위 목표 셋으로 나눠 따라갑니다.

1합 모으기의 세 하위 목표

1부터 3까지의 합을 구하는 풀이 예제입니다. 코드를 하는 일 셋으로 나누고 주석 머리줄(//)을 달았습니다. 이렇게 나눈 일 하나하나를 하위 목표(subgoal)라고 부릅니다.

// 1. 합을 0으로
let total = 0;
// 2. 하나씩 꺼내 더하기
for (let n = 1; n < 4; n++) {
  total = total + n;
}
// 3. 끝나고 쓰기
console.log(total);
실행 결과
6
  • 1. 합을 0으로: 반복 앞에서 total을 만들어 0에 붙입니다. 아직 아무것도 더하지 않은 합입니다.
  • 2. 하나씩 꺼내 더하기: 5번 줄은 오른쪽을 먼저 계산합니다. 지금 total에 n을 더한 값을 만들고, 그 값에 total을 다시 붙입니다(규칙 2). 바퀴마다 total이 1, 3, 6으로 커집니다.
  • 3. 끝나고 쓰기: 반복이 다 끝난 뒤 한 번 찍습니다. 그래서 console.log(total);은 닫는 중괄호 밖에 둡니다.

추적 표로 따라가면 total이 커지는 모습이 보입니다.

줄바뀐 이름값출력
2total0
4n1
4조건 n < 4true
5total1
4n2
4조건 n < 4true
5total3
4n3
4조건 n < 4true
5total6
4n4
4조건 n < 4false
86

n처럼 반복이 차례로 바꿔 가는 이름을 걸음꾼, total처럼 값을 모아 가는 이름을 모으는 값이라고 부릅니다. 역할을 알면 처음 보는 코드도 빨리 읽힙니다. 1부터 100까지 더하려면 조건 칸만 n <= 100으로 바꾸면 됩니다(5050). 바퀴가 100번으로 늘어도 코드는 그대로입니다. total = total + n;은 total += n;으로 줄여 쓸 수도 있습니다. 수에서는 뜻이 같습니다. 이 과목은 계산 차례가 잘 보이는 앞의 꼴로 씁니다.

2세기 — 맞으면 1 더하기

세기도 같은 틀입니다. 값을 더하는 대신 조건이 맞을 때만 1을 더하면, 그 합이 곧 개수입니다. 1부터 10까지 가운데 3으로 나누어떨어지는 수를 셉니다. n % 3은 n을 3으로 나눈 나머지입니다.

// 1. 합을 0으로
let count = 0;
// 2. 하나씩 꺼내 맞으면 1 더하기
for (let n = 1; n < 11; n++) {
  if (n % 3 === 0) {
    count = count + 1;
  }
}
// 3. 끝나고 쓰기
console.log(count);
실행 결과
3

n이 3, 6, 9일 때만 조건이 true라서 6번 줄이 세 번 실행됩니다. 하위 목표 셋의 짜임은 합 모으기와 같고, 2번 하위 목표 안에 조건 하나가 더 들었을 뿐입니다.

3console.log를 어디에 두는가

1절 코드에서 console.log(total);을 닫는 중괄호 안으로 옮겼습니다. 무엇이 찍힐지 정한 뒤 펼쳐 보세요.

let total = 0;
for (let n = 1; n < 4; n++) {
  total = total + n;
  console.log(total);
}
실행 결과 보기
실행 결과
1
3
6

예상과 다르면 그곳이 배울 곳입니다. 중괄호 안의 줄은 바퀴마다 실행되어 그때까지의 합을 세 번 찍습니다. 1절처럼 중괄호 밖에 두면 반복이 다 끝난 뒤 한 번 6을 찍습니다. 어느 덩어리에 드는지는 중괄호가 정합니다(규칙 4).

합을 한 번만 쓰려면 '끝나고 쓰기'대로 닫는 중괄호 밖에 둡니다. 거꾸로 결과가 추적 표와 다를 때는 덩어리 안에 console.log를 잠깐 넣어 바퀴마다 값을 찍어 봅니다(값을 찍어 보며 고치기에서 다룹니다).

예제

합을 0으로 두지 않으면

1번 하위 목표를 빠뜨렸습니다.

for (let n = 1; n < 4; n++) {
  total = total + n;
}
console.log(total);
실행 결과
main.js:2  total = total + n;  ^ ReferenceError: total is not defined    at main.js:2:3

ReferenceError 줄의 total is not defined는 'total이 정의되어 있지 않다', 곧 그런 이름이 없다는 뜻입니다. 2번 줄에서 처음 쓰는 total을 let으로 만든 적이 없습니다. 오류는 2번 줄에서 났지만 고칠 곳은 반복 앞입니다. let total = 0;을 1번 줄에 넣습니다.

자주 틀리는 곳

틀린 생각: 이름이 total이면 자바스크립트가 알아서 값을 더해 합을 만든다.

total은 영어로 '합계'라서, 그 이름을 쓰면 값이 저절로 쌓일 것처럼 읽힙니다. 자바스크립트는 이름의 뜻을 모릅니다.

let total = 0;
for (let n = 1; n < 4; n++) {
  total = n;
}
console.log(total);
실행 결과
3

3번 줄은 바퀴마다 total을 n에 다시 붙일 뿐이라, 마지막 바퀴의 3만 남습니다.

맞는 규칙: 자바스크립트는 이름의 뜻을 모르고 쓴 식대로만 계산합니다. 더하려면 total = total + n;처럼 더하는 식을 씁니다(규칙 6).

틀린 생각: 합을 0으로 두는 줄은 반복 안에 둬도 한 번만 실행된다.

합을 0으로 두는 일은 처음에 한 번 하는 일이라, 어디에 두든 한 번만 실행될 것 같습니다. 그러나 중괄호 안의 줄은 바퀴마다 실행됩니다.

for (let n = 1; n < 4; n++) {
  let total = 0;
  total = total + n;
}
console.log(total);

바퀴마다 새 total이 0에서 시작하고, 반복이 끝나면 total도 사라집니다. 그래서 5번 줄에서 예제의 오류와 같은 total is not defined로 멈춥니다.

맞는 규칙: 합을 0으로 두는 줄은 반복 앞에 써서 한 번만 실행되게 합니다. 반복 안에서 let으로 만든 이름은 그 중괄호 안에서만 삽니다(규칙 4).

확인 문제

1. 1절 풀이 예제의 조건을 n < 5로 바꿨습니다(주석은 뺐습니다). 무엇이 찍히는지 쓰세요.

let total = 0;
for (let n = 1; n < 5; n++) {
  total = total + n;
}
console.log(total);
힌트

n이 바퀴마다 붙는 값을 먼저 적고, 바퀴마다 total을 추적 표에 씁니다.

정답
실행 결과
10

n은 1, 2, 3, 4일 때 덩어리를 실행합니다. total은 0 → 1 → 3 → 6 → 10입니다.

흔한 오답은 15입니다. 조건의 끝 수 5도 든다고 본 것입니다(끝도 든다는 생각). 5 < 5는 false입니다.

2. 빈칸을 채워 코드를 완성하세요.

(가) 1부터 5까지의 합 15가 찍히도록 한 줄의 빈칸을 채우세요.

// 1. 합을 0으로
let total = 0;
// 2. 하나씩 꺼내 더하기
for (let n = 1; n < 6; n++) {
  total = ________;
}
// 3. 끝나고 쓰기
console.log(total);
힌트

2번 하위 목표 '하나씩 꺼내 더하기'입니다.

정답

total + n입니다. 다르게 써도 되는 곳: n + total로 써도 같습니다.

빈칸에 15를 바로 써도 15가 찍히지만, 조건을 n < 11로 바꾸면 55가 아니라 15가 그대로 찍힙니다. 합을 모으려면 n을 더해야 합니다.

흔한 오답은 n만 쓰는 것입니다(이름이 뜻을 정한다는 생각). 그러면 바퀴마다 total이 n에 다시 붙기만 해서 마지막 값 5가 찍힙니다.

(나) 1부터 8까지 가운데 짝수의 개수를 세는 코드입니다. 2번 하위 목표를 통째로 채우세요. 다 채운 코드는 4를 찍어야 합니다(2, 4, 6, 8).

// 1. 합을 0으로
let count = 0;
// 2. 하나씩 꺼내 맞으면 1 더하기

// 3. 끝나고 쓰기
console.log(count);
힌트

2절 세기 코드의 2번 하위 목표와 같은 꼴입니다. 짝수는 2로 나눈 나머지가 0입니다.

정답

주석을 뺀, 다 채운 코드입니다. 2~6번 줄이 2번 하위 목표입니다.

let count = 0;
for (let n = 1; n < 9; n++) {
  if (n % 2 === 0) {
    count = count + 1;
  }
}
console.log(count);
실행 결과
4

다르게 써도 되는 곳: count = count + 1;은 count += 1;로, 조건 칸은 n <= 8로 써도 같습니다.

흔한 오답은 count = count + 1; 자리에 count = n;을 쓰는 것입니다(이름이 뜻을 정한다는 생각). 마지막 짝수 8이 찍힙니다.

3. 사흘 동안 걸은 걸음 수의 합을 구하려 합니다. 1000, 2000, 3000걸음을 걸었으니 합은 6000이어야 하는데, 3000이 찍혔습니다. 몇 번 줄을 어떻게 고쳐야 할까요?

let total = 0;
for (let i = 1; i < 4; i++) {
  const steps = i * 1000;
  total = steps;
}
console.log(total);
실행 결과
3000
힌트

2번 하위 목표 '하나씩 꺼내 더하기'가 정말 더하고 있는지 봅니다.

정답

4번 줄을 total = total + steps;⁠로 고치면 6000이 찍힙니다.

고치기 전 4번 줄은 바퀴마다 total을 그날 걸음 수에 다시 붙일 뿐이라 마지막 날의 3000만 남았습니다. 이름이 total이어도 자바스크립트는 알아서 더하지 않습니다(규칙 6).

다르게 고쳐도 되는 곳: total += steps;로 써도 6000이 찍힙니다.

흔한 오답은 6번 줄을 덩어리 안으로 옮기는 것입니다. 그러면 1000, 2000, 3000이 줄마다 찍힐 뿐 합은 구해지지 않습니다.

컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요. 2절 세기 코드를 main.js에 저장해 돌립니다. 그다음 마지막 줄 console.log(count);를 6번 줄 아래(if 덩어리 안)로 옮기면 무엇이 찍힐지 먼저 적고, 옮겨 돌려서 맞춰 봅니다. 저장하고 돌리는 법은 내 컴퓨터에서 돌려 보기에 있습니다.

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

자바스크립트 목차로