4.1 조건문 (Conditional Statements)
조건문은 조건식의 결과에 따라 블록 { } 내부의 실행 경로를 변경할 때 사용됩니다. 크게 if문과 switch문이 있습니다. 조건문을 잘 활용하면 복잡한 비즈니스 로직을 명확하고 읽기 쉬운 코드로 표현할 수 있습니다.
1. if 문 기본 구조
if문은 가장 기본적인 조건문입니다. 조건식이 true일 때만 블록 안의 문장들을 실행합니다.
단순 if 문
int score = 85;
if (score >= 60) {
System.out.println("합격입니다!");
}
// 조건이 false이면 블록을 건너뜁니다.
실행할 문장이 딱 한 줄이면 중괄호를 생략할 수 있습니다. 하지만 나중에 문장을 추가할 때 버그가 생기기 쉬우므로 항상 중괄호를 쓰는 습관 을 들이는 것이 좋습니다.
if (score >= 60)
System.out.println("합격!"); // 중괄호 생략 가능하지만 비권장
if-else 문
조건이 true일 때와 false일 때 각각 다른 코드를 실행합니다.
int score = 45;
if (score >= 60) {
System.out.println("합격입니다!");
} else {
System.out.println("불합격입니다. 다음 기회에!");
}
if-else if-else 체인
여러 조건을 순서대로 검사할 때 사용합니다. 위에서 아래로 순서대로 조건을 검사하며, 처음으로 true인 블록만 실행됩니다.
int score = 85;
if (score >= 90) {
System.out.println("A등급입니다.");
} else if (score >= 80) { // 90 미만이고 80 이상인 경우
System.out.println("B등급입니다.");
} else if (score >= 70) {
System.out.println("C등급입니다.");
} else if (score >= 60) {
System.out.println("D등급입니다.");
} else { // 60 미만인 모든 경우
System.out.println("F등급입니다.");
}
// 출력: B등급입니다.
2. 중첩 if 문
if문 블록 안에 또 다른 if문을 작성할 수 있습니다. 중첩 횟수에는 제한이 없지만, 너무 깊이 중첩되면 가독성이 크게 떨어집니다.
int score = 95;
char opt = ' ';
if (score >= 90) {
// 외부 if: 90점 이상
if (score >= 98) {
opt = '+'; // 98점 이상: A+
} else if (score < 94) {
opt = '-'; // 90~93점: A-
}
// 94~97점: 그냥 A (opt는 ' ' 그대로)
}
System.out.println("당신의 학점은 A" + opt + " 입니다.");
// 출력: 당신의 학점은 A 입니다. (95점이므로 opt는 공백)
중첩이 3단계 이상 깊어지면 코드 흐름을 파악하기 어려워집니다. early return 패턴 또는 로직 분리로 중첩을 줄이는 것을 권장합니다.
// 나쁜 예: 3단계 중첩
if (user != null) {
if (user.isActive()) {
if (user.hasPermission()) {
doSomething();
}
}
}
// 좋은 예: 조기 반환(early return)으로 중첩 제거
if (user == null) return;
if (!user.isActive()) return;
if (!user.hasPermission()) return;
doSomething();
3. switch 문 (전통 방식, Java 14 이전)
조건의 경우의 수가 많을 때 다중 if-else문보다 switch문이 훨씬 가독성이 좋고 빠릅니다. switch문은 조건식이 아니라 정확한 '값'이 일치하는지 를 확인합니다.
기본 구조
int month = 4;
String season;
switch (month) {
case 3:
case 4:
case 5:
season = "봄";
break; // switch 블록 탈출
case 6:
case 7:
case 8:
season = "여름";
break;
case 9:
case 10:
case 11:
season = "가을";
break;
default:
// 해당하는 case가 전혀 없을 때 실행
season = "겨울";
}
System.out.println(month + "월은 " + season + "입니다."); // 4월은 봄입니다.
switch 문에서 사용 가능한 타입
| 타입 | 예시 |
|---|---|
| byte, short, int | switch(score) |
| char | switch(grade) |
| String (Java 7+) | switch(command) |
| enum | switch(season) |
long, float, double은 switch 표현식에 사용할 수 없습니다. 이 타입들은 if문을 사용해야 합니다.
4. fall-through 버그: break 누락 주의
switch문에서 가장 흔한 실수는 break를 누락하는 것입니다. break가 없으면 해당 case를 실행한 후 다음 case로 계속 흘러내려가는 fall-through 현상이 발생합니다.
int day = 2; // 화요일
String result = "";
switch (day) {
case 1:
result += "월요일 ";
// break 누락!
case 2:
result += "화요일 ";
// break 누락!
case 3:
result += "수요일 ";
break; // 여기서 탈출
case 4:
result += "목요일 ";
break;
}
System.out.println(result);
// 예상: "화요일 "
// 실제 출력: "화요일 수요일 " ← fall-through 버그!
의도적인 fall-through 활용
때로는 fall-through를 의도적으로 활용하기도 합니다.
int month = 4;
int days;
switch (month) {
case 1: case 3: case 5: case 7:
case 8: case 10: case 12:
days = 31;
break;
case 4: case 6: case 9: case 11:
days = 30;
break;
case 2:
days = 28; // 윤년 무시
break;
default:
days = -1; // 잘못된 월
}
System.out.println(month + "월은 " + days + "일입니다."); // 4월은 30일입니다.
5. 조건 연산자 (삼항 연산자) ?:
if-else의 축약 표현입니다. 간단한 값 선택에 사용하면 코드를 간결하게 만들 수 있습니다.
// 문법: (조건식) ? true일 때 값 : false일 때 값
int score = 75;
// if-else 방식
String result1;
if (score >= 60) {
result1 = "합격";
} else {
result1 = "불합격";
}
// 삼항 연산자 방식 (동일한 결과)
String result2 = (score >= 60) ? "합격" : "불합격";
System.out.println(result2); // 합격
// 중첩 삼항 연산자 (가독성 주의)
int score = 85;
String grade = (score >= 90) ? "A" :
(score >= 80) ? "B" :
(score >= 70) ? "C" : "F";
System.out.println("등급: " + grade); // 등급: B
삼항 연산자를 중첩해서 쓰면 가독성이 나빠집니다. 조건이 3개 이상이면 if-else if 체인이나 switch를 사용하는 것이 더 명확합니다.
6. if vs switch 선택 기준
| 상황 | 권장 방식 |
|---|---|
범위 조건 (score >= 90) | if-else if |
| 특정 값 비교 (3가지 이상) | switch |
| 2가지 선택 | if-else 또는 삼항 연산자 |
복잡한 복합 조건 (&&, ||) | if-else if |
| enum 타입 분기 | switch 표현식 (Java 14+) |
7. 실전 예제 1: 학점 계산기
점수를 입력받아 학점(A/B/C/D/F)을 계산하는 프로그램입니다.
import java.util.Scanner;
public class GradeCalculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("점수를 입력하세요 (0~100): ");
int score = scanner.nextInt();
// 입력값 유효성 검사
if (score < 0 || score > 100) {
System.out.println("잘못된 점수입니다. 0~100 사이 값을 입력하세요.");
scanner.close();
return;
}
String grade;
String comment;
if (score >= 90) {
grade = "A";
comment = "훌륭합니다!";
} else if (score >= 80) {
grade = "B";
comment = "잘했습니다!";
} else if (score >= 70) {
grade = "C";
comment = "보통입니다.";
} else if (score >= 60) {
grade = "D";
comment = "조금 더 노력하세요.";
} else {
grade = "F";
comment = "재수강이 필요합니다.";
}
System.out.println("점수: " + score);
System.out.println("학점: " + grade);
System.out.println(comment);
scanner.close();
}
}
실행 예시:
점수를 입력하세요 (0~100): 85
점수: 85
학점: B
잘했습니다!
8. 실전 예제 2: 요일별 스케줄 출력 (switch 활용)
import java.util.Scanner;
public class DailySchedule {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("요일을 입력하세요 (월/화/수/목/금/토/일): ");
String day = scanner.next();
String schedule;
String type;
switch (day) {
case "월":
schedule = "팀 미팅 오전 9시, 주간 계획 수립";
type = "평일";
break;
case "화":
schedule = "코드 리뷰 오후 2시";
type = "평일";
break;
case "수":
schedule = "점심 팀 빌딩, 오후 기술 세미나";
type = "평일";
break;
case "목":
schedule = "1:1 미팅, 스프린트 진행 상황 점검";
type = "평일";
break;
case "금":
schedule = "스프린트 회고, 배포 준비";
type = "평일";
break;
case "토":
schedule = "개인 프로젝트, 운동";
type = "주말";
break;
case "일":
schedule = "가족 시간, 다음 주 준비";
type = "주말";
break;
default:
schedule = "알 수 없는 요일입니다.";
type = "오류";
}
System.out.println("[" + type + "] " + day + "요일 일정: " + schedule);
scanner.close();
}
}
실행 예시:
요일을 입력하세요 (월/화/수/목/금/토/일): 수
[평일] 수요일 일정: 점심 팀 빌딩, 오후 기술 세미나
9. 실전 예제 3: 로그인 시스템 시뮬레이션
중첩 조건문의 실제 활용 예시입니다.
public class LoginSystem {
public static void main(String[] args) {
String inputId = "admin";
String inputPw = "1234";
// 실제로는 DB에서 가져온다고 가정
String correctId = "admin";
String correctPw = "admin123";
boolean isAccountLocked = false;
int loginAttempts = 3;
if (isAccountLocked) {
System.out.println("계정이 잠겨 있습니다. 관리자에게 문의하세요.");
} else {
if (inputId.equals(correctId)) {
if (inputPw.equals(correctPw)) {
System.out.println("로그인 성공! 환영합니다, " + inputId + "님.");
} else {
System.out.println("비밀번호가 틀렸습니다. 남은 시도: " + (loginAttempts - 1) + "회");
}
} else {
System.out.println("존재하지 않는 아이디입니다.");
}
}
}
}
조건문 최적화 원칙:
- 가장 자주 발생하는 조건을 앞에 배치- 평균 비교 횟수가 줄어듭니다.
- 복잡한 조건은 변수로 추출-
boolean isValid = score >= 0 && score <= 100;처럼 조건을 명명합니다. - switch 표현식(Java 14+) 활용- 전통 switch의 fall-through 버그를 원천 차단합니다.
- null 체크를 먼저-
if (str != null && str.equals("value"))순서로 작성하면 NullPointerException을 방지합니다.