조건에 따라 다른 코드를 실행하고, 같은 작업을 반복하고, 특정 조건에서 빠져나오기 — 이 세 가지만 할 수 있으면 어떤 로직이든 만들 수 있다. Java의 제어문과 반복문을 한 번에 정리해보자.

조건문 — if/else

기본 구조

if는 조건을 위에서 아래로 검사하고, 처음 true가 되는 블록만 실행해요.

JAVA
int score = 85;

if (score >= 90) {
    System.out.println("A");
} else if (score >= 80) {
    System.out.println("B");
} else {
    System.out.println("F");
}
// 출력: B

else는 선택입니다. 모든 조건에 해당하지 않을 때의 기본 동작을 정의해요.

중괄호를 생략하면 생기는 문제

JAVA
if (score >= 90)
    System.out.println("A");
    System.out.println("축하합니다"); // 이건 항상 실행됨!

중괄호 없이 쓰면 바로 다음 한 줄만 if에 속합니다. 들여쓰기가 같아도 두 번째 줄은 if와 무관하게 항상 실행돼요. 이런 실수를 방지하려면 ** 중괄호를 항상 쓰는 게 좋습니다.**

삼항 연산자

간단한 조건은 한 줄로 쓸 수 있어요.

JAVA
String grade = (score >= 90) ? "A" : "B 이하";

조건 ? 참일 때 값 : 거짓일 때 값 형태입니다. 중첩하면 가독성이 급격히 떨어지므로 한 단계만 쓰는 게 좋아요.

조건문 — switch

여러 값 중 하나를 선택할 때는 switchif-else if 체인보다 깔끔할 수 있습니다.

전통적인 switch와 fall-through 문제

전통 switch에서는 각 case 끝에 break를 써야 합니다. break를 빼먹으면 다음 case로 쭉 떨어지는데, 이걸 fall-through 라고 해요.

JAVA
switch (day) {
    case 1:
        System.out.println("월요일");
        // break 없음 → 아래로 쭉 실행
    case 2:
        System.out.println("화요일");
    case 3:
        System.out.println("수요일");
}
// day가 1이면: 월요일, 화요일, 수요일 모두 출력!

의도적으로 쓰는 경우도 있지만, 대부분은 실수입니다. Java 14에서 이 문제를 근본적으로 해결한 문법이 나왔어요.

Enhanced switch (Java 14+)

화살표() 문법은 fall-through가 원천적으로 불가능합니다. 해당 case만 실행되고, break도 필요 없어요.

JAVA
switch (day) {
    case 1 -> System.out.println("월요일");
    case 2 -> System.out.println("화요일");
    case 3 -> System.out.println("수요일");
    case 6, 7 -> System.out.println("주말");
    default -> System.out.println("기타");
}

여러 값을 콤마로 묶을 수도 있어요 (case 6, 7). 전통 switch에서는 이렇게 하려면 fall-through를 의도적으로 써야 했는데, 화살표 문법에서는 깔끔하게 표현됩니다.

switch 표현식 — 값을 반환하는 switch

switch를 표현식 으로 쓰면 값을 직접 반환할 수 있습니다.

JAVA
String dayName = switch (day) {
    case 1 -> "월요일";
    case 2 -> "화요일";
    case 3 -> "수요일";
    case 6, 7 -> "주말";
    default -> "기타";
};

여러 줄이 필요하면 블록으로 감싸고 yield를 씁니다.

JAVA
String description = switch (day) {
    case 1, 2, 3, 4, 5 -> {
        String name = getDayName(day);
        yield name + " (평일)";
    }
    case 6, 7 -> "주말";
    default -> "잘못된 입력";
};

반복문 — for

기본 for문

for (초기화; 조건; 증감) 구조로, 반복 횟수가 정해져 있을 때 씁니다.

JAVA
for (int i = 0; i < 5; i++) {
    System.out.println(i);
}
// 0, 1, 2, 3, 4
  1. **초기화 **: 반복 변수 선언 (int i = 0)
  2. ** 조건 **: true인 동안 반복 (i < 5)
  3. ** 증감 **: 매 반복이 끝난 후 실행 (i++)

for-each — 인덱스가 필요 없을 때

배열이나 컬렉션을 순회할 때는 for-each가 간결해요.

JAVA
int[] numbers = {10, 20, 30, 40, 50};

for (int num : numbers) {
    System.out.println(num);
}

인덱스가 필요하면 기본 for문을 쓰면 됩니다. for-each에서는 인덱스에 접근할 수 없기 때문이에요.

JAVA
for (int i = 0; i < names.length; i++) {
    System.out.println(i + ": " + names[i]);
}

반복문 — while / do-while

while

조건이 true인 동안 반복합니다. 반복 횟수가 정해져 있으면 for, 조건 기반이면 while이 자연스러워요.

JAVA
int count = 0;
while (count < 5) {
    System.out.println(count);
    count++;
}

do-while — 최소 한 번 실행 보장

do-while은 조건을 ** 나중에** 검사하기 때문에 최소 한 번은 실행됩니다.

JAVA
int count = 10;

do {
    System.out.println("do-while: " + count);
    count++;
} while (count < 5);
// 출력: do-while: 10 (조건이 false지만 한 번은 실행됨)

while이었다면 한 번도 실행되지 않았을 코드예요. "입력 검증" 같이 최소 한 번은 사용자 입력을 받아야 하는 경우에 유용합니다.

break와 continue

break — 반복문 탈출

JAVA
for (int i = 0; i < 10; i++) {
    if (i == 5) break;
    System.out.println(i);
}
// 0, 1, 2, 3, 4

continue — 현재 반복 건너뛰기

JAVA
for (int i = 0; i < 10; i++) {
    if (i % 2 == 0) continue; // 짝수면 건너뜀
    System.out.println(i);
}
// 1, 3, 5, 7, 9

레이블(Label) — 중첩 반복문 탈출

break는 가장 안쪽 반복문만 탈출합니다. 중첩 반복문에서 바깥까지 한 번에 빠져나오려면 레이블을 써야 해요.

JAVA
outer:
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        if (i == 1 && j == 1) {
            break outer; // 바깥 for문까지 탈출
        }
        System.out.println(i + ", " + j);
    }
}
// 0,0 → 0,1 → 0,2 → 1,0 에서 멈춤

레이블은 중첩 탈출에 유용하지만, 너무 많이 쓰면 코드가 읽기 어려워집니다. 가능하면 메서드를 분리하는 게 더 깔끔해요.

주의할 점

1. 무한 루프에 빠지기

JAVA
int i = 0;
while (i < 10) {
    System.out.println(i);
    // i++를 빼먹으면 영원히 0만 출력
}

증감 연산을 빠뜨려서 무한 루프에 빠지는 건 가장 흔한 실수입니다. while을 쓸 때는 ** 루프 탈출 조건이 반드시 갱신되는지** 확인해야 해요.

2. off-by-one 에러

JAVA
int[] arr = {10, 20, 30};

// 잘못된 코드 — arr[3]은 존재하지 않음
for (int i = 0; i <= arr.length; i++) { // <= 가 문제!
    System.out.println(arr[i]); // ArrayIndexOutOfBoundsException
}

배열 인덱스는 0부터 시작하고 length는 개수이므로 마지막 인덱스는 length - 1이에요. i <= arr.length가 아니라 i < arr.length가 맞습니다. 경계값 처리 실수는 반복문에서 가장 자주 발생하는 버그 유형이에요.

3. switch에서 break 빠뜨리기

전통 switch에서 break를 빠뜨리면 fall-through가 발생합니다. 이 버그는 컴파일 에러가 나지 않기 때문에 찾기 어려워요. ** 가능하면 화살표 문법을 쓰는 것 **이 이 실수를 원천 차단하는 방법입니다.

JAVA
// 화살표 문법 — fall-through 불가능
switch (value) {
    case 1 -> doFirst();
    case 2 -> doSecond();
    default -> doDefault();
}

TIP 이 글의 코드 예제를 직접 실행해보고 싶다면 Java 기본기 핸드북을 확인해보세요.

정리

항목설명
if/else조건 분기의 기본. 중괄호를 항상 쓰자
switch (전통)여러 값 비교. break 빠뜨리면 fall-through 발생
switch (화살표)Java 14+. fall-through 없음, 값 반환 가능
for정해진 횟수 반복. 배열/컬렉션 순회 시 for-each 활용
while / do-while조건 기반 반복. do-while은 최소 한 번 실행 보장
break / continuebreak는 탈출, continue는 건너뛰기
레이블중첩 반복문 바깥 탈출 시 사용. 남용하지 말 것

다음 글에서는 메서드와 배열을 다뤄볼게요. 코드를 나누는 방법(메서드)과 데이터를 묶는 방법(배열)은 어떤 프로그램이든 기본이 되는 주제입니다.

댓글 로딩 중...