반복문은 중복을 규칙으로 바꿉니다
프로그램에는 같은 동작을 여러 번 해야 하는 순간이 많습니다. 블록 10개를 놓고, 점수 목록을 합산하고, 사용자가 올바른 값을 입력할 때까지 다시 묻고, 배열의 모든 원소를 출력합니다. 출력문을 복사해 10줄로 늘릴 수도 있지만, 개수가 바뀌면 다시 수정해야 하고 실수도 늘어납니다. 반복문은 “어디서 시작하고, 언제까지 계속하고, 매번 무엇을 바꿀지”를 코드로 표현합니다.
반복문을 배울 때는 세 질문을 항상 붙잡으세요.
- 반복 전에 어떤 값이 준비되어야 하나요?
- 반복은 어떤 조건일 때 계속되어야 하나요?
- 반복이 한 번 끝날 때 다음 상태로 어떻게 이동하나요?
이 세 가지가 명확하면 for와 while 모두 어렵지 않습니다. 반대로 셋 중 하나가 흐리면 무한 반복, 한 번 덜 실행, 한 번 더 실행 같은 오류가 생깁니다.
for문의 세 부분 읽기
for문은 반복 횟수나 인덱스가 분명할 때 좋습니다.
for (초기식; 조건식; 증감식) {
반복할 코드
}
초기식은 반복이 시작되기 전에 한 번 실행됩니다. 조건식은 반복 본문을 실행하기 전에 검사됩니다. 증감식은 본문이 한 번 끝난 뒤 실행됩니다. 그다음 다시 조건식을 검사합니다.
for로 벽 한 줄 쌓기
public class Main {
public static void main(String[] args) {
int wallLength = 6;
for (int position = 1; position <= wallLength; position++) {
System.out.println(position + "번 위치에 블록 설치");
}
System.out.println("벽 한 줄 완성");
}
}
예상 출력은 다음과 같습니다.
1번 위치에 블록 설치
2번 위치에 블록 설치
3번 위치에 블록 설치
4번 위치에 블록 설치
5번 위치에 블록 설치
6번 위치에 블록 설치
벽 한 줄 완성
position은 1에서 시작하고, position <= wallLength가 참인 동안 본문을 실행합니다. 한 번 실행할 때마다 position++으로 1 증가합니다. 7이 되면 조건이 거짓이므로 반복을 빠져나옵니다.
<=와 <의 차이를 의식하세요. 사람이 세는 위치처럼 1부터 6까지 포함하려면 <= 6이 자연스럽습니다. 배열 인덱스처럼 0부터 시작하고 길이보다 작아야 하는 경우에는 < length가 기본입니다.
누적 계산하기
반복문은 단순 출력보다 누적 계산에서 더 자주 쓰입니다.
public class Main {
public static void main(String[] args) {
int total = 0;
for (int day = 1; day <= 5; day++) {
int gathered = day * 3;
total += gathered;
System.out.println(day + "일차 수집: " + gathered + ", 누적: " + total);
}
System.out.println("최종 수집량: " + total);
}
}
total은 반복 밖에서 준비해야 합니다. 반복 안에서 매번 새로 0이 되면 누적이 아니라 매회 초기화가 됩니다. 반복문을 작성할 때 변수의 위치는 매우 중요합니다. 반복마다 새로 만들어야 하는 값은 본문 안에, 반복 전체에서 유지해야 하는 값은 반복문 밖에 둡니다.
while은 상태가 바뀔 때까지 반복합니다
while은 반복 횟수보다 종료 조건이 더 중요할 때 어울립니다.
public class Main {
public static void main(String[] args) {
int health = 3;
int restCount = 0;
while (health < 12) {
health += 3;
restCount++;
System.out.println(restCount + "회 휴식 후 체력: " + health);
}
System.out.println("탐험 재개 가능");
}
}
예상 출력은 다음과 같습니다.
1회 휴식 후 체력: 6
2회 휴식 후 체력: 9
3회 휴식 후 체력: 12
탐험 재개 가능
while을 쓸 때 가장 먼저 확인할 것은 조건에 사용한 값이 반복 안에서 바뀌는지입니다. 위 예제에서 health += 3이 빠지면 health < 12가 계속 참이어서 반복이 끝나지 않습니다.
do-while은 최소 한 번 실행합니다
Java에는 do-while도 있습니다. 조건 검사보다 본문 실행이 먼저이므로 최소 한 번은 실행됩니다.
public class Main {
public static void main(String[] args) {
int attempts = 0;
boolean connected;
do {
attempts++;
connected = attempts >= 3;
System.out.println("연결 시도: " + attempts);
} while (!connected);
System.out.println("연결 완료");
}
}
입문 단계에서는 for와 while만으로도 대부분의 예제를 해결할 수 있습니다. 다만 “한 번 실행한 뒤 계속 여부를 판단한다”는 흐름이 필요할 때 do-while이 존재한다는 정도는 알아두면 좋습니다.
break와 continue의 차이
break는 반복문 전체를 끝냅니다. continue는 현재 반복의 남은 코드를 건너뛰고 다음 반복으로 넘어갑니다.
public class Main {
public static void main(String[] args) {
for (int slot = 1; slot <= 8; slot++) {
if (slot == 3) {
continue;
}
if (slot == 7) {
break;
}
System.out.println(slot + "번 슬롯 검사");
}
}
}
출력되는 슬롯은 1, 2, 4, 5, 6입니다. 3번은 건너뛰고, 7번에서 반복문을 완전히 종료합니다. continue와 break는 유용하지만 너무 많이 쓰면 흐름이 튀어 보입니다. 간단한 조건 정리로 해결할 수 있으면 조건식을 조정하는 편이 더 읽기 좋을 때도 많습니다.
중첩 반복문과 좌표 출력
반복문 안에 반복문을 넣으면 2차원 구조를 다룰 수 있습니다.
public class Main {
public static void main(String[] args) {
int width = 4;
int height = 3;
for (int y = 1; y <= height; y++) {
for (int x = 1; x <= width; x++) {
System.out.print("(" + x + "," + y + ") ");
}
System.out.println();
}
}
}
예상 출력은 다음과 같습니다.
(1,1) (2,1) (3,1) (4,1)
(1,2) (2,2) (3,2) (4,2)
(1,3) (2,3) (3,3) (4,3)
바깥 반복은 행을 담당하고, 안쪽 반복은 열을 담당합니다. 안쪽 반복이 한 줄의 모든 좌표를 출력한 뒤 System.out.println()으로 줄을 바꿉니다. 중첩 반복문에서는 변수 이름을 i, j로만 두기보다 row, column, x, y처럼 의미를 드러내면 읽기 쉽습니다.
흔한 반복문 오류
가장 흔한 오류는 한 번 더 실행되거나 한 번 덜 실행되는 문제입니다. position < wallLength와 position <= wallLength는 결과가 다릅니다. 시작값이 0인지 1인지에 따라 조건도 달라집니다.
또 다른 오류는 반복 조건이 끝나는 방향으로 변하지 않는 것입니다.
int count = 0;
while (count < 5) {
System.out.println(count);
}
이 코드는 count가 증가하지 않아 끝나지 않습니다. count++가 필요합니다. 무한 반복이 의도된 경우에도 break 조건이나 외부 종료 방법이 있어야 합니다.
반복문 안에서 누적 변수를 잘못 선언하는 실수도 많습니다.
for (int day = 1; day <= 3; day++) {
int total = 0;
total += day;
}
total이 반복마다 새로 만들어져 누적되지 않습니다. 반복 후에도 결과를 써야 한다면 반복문 밖에 선언해야 합니다.
반복문을 추적하는 표 만들기
반복문이 헷갈릴 때는 머릿속으로만 따라가지 말고 표를 만들어 보세요. 열은 반복 변수, 조건 결과, 출력, 반복 후 변화 정도면 충분합니다. 예를 들어 for (int position = 1; position <= 3; position++)라면 첫 행은 position 1, 조건 참, 출력 1번, 증가 후 2입니다. 둘째 행은 2, 셋째 행은 3입니다. 넷째 검사에서 position은 4이고 조건이 거짓이므로 본문은 실행되지 않습니다.
이 표는 한 번 더 실행되는 오류를 잡는 데 매우 효과적입니다. 조건을 <로 써야 하는지 <=로 써야 하는지 헷갈릴 때 실제 값을 넣어 보면 바로 보입니다. 배열에서는 인덱스 0부터 시작하므로 길이가 4이면 0, 1, 2, 3까지만 접근해야 합니다. 표를 그리면 왜 index < array.length가 자연스러운지 손으로 확인할 수 있습니다.
while문도 같은 방식으로 추적할 수 있습니다. 다만 while에서는 조건에 쓰인 값이 반복 안에서 어떻게 바뀌는지 더 주의해야 합니다. 값이 종료 방향으로 움직이지 않으면 반복은 끝나지 않습니다. 값이 너무 크게 바뀌면 목표를 지나칠 수 있습니다. 지나치는 것이 허용되는지, 정확히 같은 값에서 멈춰야 하는지 요구사항을 확인하세요.
반복문 안의 책임을 작게 유지하기
반복문 안에 너무 많은 일을 넣으면 흐름을 읽기 어렵습니다. 한 반복에서 무엇을 하는지 한 문장으로 설명할 수 있어야 합니다. “각 슬롯을 검사한다”, “각 날짜의 수집량을 누적한다”, “각 좌표를 출력한다”처럼 말할 수 있으면 좋습니다. 만약 “검사하고, 변환하고, 저장하고, 출력하고, 조건에 따라 다른 배열도 바꾼다”처럼 길어진다면 나중에 메서드로 나눌 후보입니다.
또한 반복문 안에서 바뀌는 변수와 바깥에서 유지되는 변수를 구분하세요. 반복 변수는 보통 반복문 헤더 안에 두고, 합계나 최댓값처럼 반복 전체를 관통하는 값은 바깥에 둡니다. 조건문을 함께 사용할 때는 continue로 건너뛰는 경로가 누적 계산을 빠뜨리지 않는지 확인해야 합니다. break를 쓰면 반복 후 코드가 어떤 부분까지 처리된 상태를 기대하는지도 분명히 해야 합니다.
직접 해보기
- 벽 길이를 10으로 바꾸고 출력 횟수를 확인합니다.
for문으로 2, 4, 6, 8, 10을 출력합니다.- 1부터 100까지의 합을 구해 출력합니다.
while문으로 체력이 20 이상이 될 때까지 4씩 회복합니다.- 중첩 반복문으로 5 x 5 좌표를 출력합니다.
continue를 사용해 1부터 10 중 3의 배수를 건너뜁니다.
합계 힌트
int total = 0;을 반복문 밖에 두고, for 안에서 total += number;를 실행하면 됩니다. 반복이 끝난 뒤 total을 출력하세요.
반복문 복습 체크리스트
반복문을 배운 뒤에는 시작값, 계속 조건, 변화식을 분리해서 설명할 수 있어야 합니다. for문에서는 이 세 요소가 헤더에 모여 있고, while문에서는 초기값과 변화식이 본문 주변에 흩어져 있을 수 있습니다. 그래서 while을 읽을 때는 조건에 쓰인 변수가 어디에서 바뀌는지 더 세심하게 봐야 합니다.
다음 질문에 답해 보세요. 1부터 10까지 출력하는 반복문과 0부터 9까지 출력하는 반복문은 조건이 어떻게 다른가요? 배열 길이가 4일 때 마지막 인덱스는 무엇인가요? break와 continue는 각각 반복 흐름을 어떻게 바꾸나요? 누적 합계를 구하는 변수는 왜 반복문 밖에 있어야 하나요?
반복문은 작은 실수가 큰 차이를 만듭니다. 한 번 더 실행되면 배열 범위를 벗어날 수 있고, 한 번 덜 실행되면 마지막 데이터가 빠집니다. 종료 방향으로 값이 변하지 않으면 프로그램이 멈춘 것처럼 보일 수 있습니다. 그래서 반복문을 만들 때는 처음 값, 마지막으로 실행되는 값, 처음으로 실행되지 않는 값을 함께 확인하세요.
출력으로 반복 흐름 관찰하기
반복문을 디버깅할 때는 반복 변수와 핵심 상태를 함께 출력하면 좋습니다. 예를 들어 합계를 구한다면 현재 숫자와 누적 합계를 같이 출력합니다. 좌표를 다룬다면 현재 행과 열을 출력합니다. while로 회복을 처리한다면 회복 전 체력과 회복 후 체력을 구분해 출력합니다.
관찰이 끝나면 출력은 정리하세요. 최종 프로그램에는 사용자에게 필요한 결과만 남기고, 학습 노트에는 관찰 과정을 기록해 두면 됩니다. 이 과정을 반복하면 복잡한 반복문도 머릿속에서 막연히 상상하지 않고 실제 값의 흐름으로 읽을 수 있습니다.
이번 장의 정리
for는 반복 횟수나 인덱스가 분명할 때, while은 어떤 상태가 바뀔 때까지 반복할 때 잘 맞습니다. 반복문에서는 시작값, 계속 조건, 다음 변화가 핵심입니다. break는 반복 전체 종료, continue는 현재 회차 건너뛰기입니다. 다음 장에서는 여러 값을 한 이름으로 묶는 배열과 반복문을 함께 사용합니다.