프로그램은 상황에 따라 다른 동작을 해야 한다. 로그인 상태에 따라 화면을 바꾸고, 주문 상태에 따라 버튼을 다르게 보여주고, 권한에 따라 기능 접근을 제한한다.
Java에서는 이런 분기 처리를 조건문으로 구현한다.
ifint stock = 3;
if (stock > 0) {
System.out.println("구매 가능");
}
괄호 안의 조건식이 true일 때만 블록이 실행된다.
if-else조건이 참과 거짓 두 경우로 명확히 나뉠 때 사용한다.
boolean isLoggedIn = false;
if (isLoggedIn) {
System.out.println("마이페이지");
} else {
System.out.println("로그인 페이지");
}
else ifint responseTime = 850;
if (responseTime < 200) {
System.out.println("빠름");
} else if (responseTime < 1000) {
System.out.println("보통");
} else {
System.out.println("느림");
}
위 코드는 위에서부터 조건을 검사하다가 처음으로 참인 블록 하나만 실행한다.
if와 else if는 다르다다음 두 코드는 의미가 다르다.
if (isLoggedIn) {
System.out.println("로그인 상태");
}
if (hasCoupon) {
System.out.println("쿠폰 보유");
}
두 조건은 독립적으로 모두 실행될 수 있다.
반대로 다음 구조는 하나의 분기 그룹이다.
if (grade >= 90) {
System.out.println("A");
} else if (grade >= 80) {
System.out.println("B");
} else {
System.out.println("C");
}
처음 참이 된 한 경로만 실행된다.
Java에서는 실행 코드가 한 줄이면 중괄호를 생략할 수 있다.
if (isAdmin)
System.out.println("관리자");
하지만 코드가 추가될 때 실수하기 쉽다.
if (isAdmin) {
System.out.println("관리자");
}
팀 개발에서는 명시적으로 { }를 사용하는 편이 가독성과 유지보수에 유리하다.
switch가 편한 경우하나의 값이 특정 값과 같은지 여러 번 비교해야 한다면 switch가 읽기 쉬울 수 있다.
String status = "PAID";
switch (status) {
case "READY":
System.out.println("결제 대기");
break;
case "PAID":
System.out.println("결제 완료");
break;
case "SHIPPED":
System.out.println("배송 중");
break;
default:
System.out.println("알 수 없는 상태");
}
전통적인 switch에서는 break를 빼먹으면 다음 case까지 이어서 실행되는 fall-through가 발생할 수 있다.
최근 Java에서는 화살표 문법을 사용할 수 있다.
String message = switch (status) {
case "READY" -> "결제 대기";
case "PAID" -> "결제 완료";
case "SHIPPED" -> "배송 중";
default -> "알 수 없는 상태";
};
이 방식은 break가 필요 없고 값을 바로 반환할 수 있어 단순한 상태 분기에서 읽기 좋다.
if와 switch 선택 기준if가 자연스러운 경우범위나 복합 조건을 검사할 때다.
if (age >= 20 && isVerified) {
// ...
}
switch가 자연스러운 경우하나의 값이 여러 후보 중 무엇인지 비교할 때다.
switch (command) {
case "CREATE" -> create();
case "DELETE" -> delete();
default -> showHelp();
}
간단한 조건에 따라 값 하나를 선택해야 한다면 삼항 연산자를 사용할 수 있다.
int stock = 0;
String label = stock > 0 ? "판매중" : "품절";
형태는 다음과 같다.
조건 ? 참일 때 값 : 거짓일 때 값
짧고 단순한 선택에는 유용하지만 중첩하면 읽기 어려워진다.
좋지 않은 예:
String result = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "D";
이 정도 분기는 if 또는 switch가 더 읽기 쉽다.
조건문은 문법보다 조건의 순서가 중요하다.
int score = 95;
if (score >= 60) {
System.out.println("합격");
} else if (score >= 90) {
System.out.println("우수");
}
95도 첫 조건 score >= 60을 만족하기 때문에 두 번째 조건에는 도달하지 않는다.
더 구체적인 조건을 먼저 작성해야 한다.
if (score >= 90) {
System.out.println("우수");
} else if (score >= 60) {
System.out.println("합격");
}
else if는 위에서부터 검사하다가 처음 참인 블록 하나만 실행한다.
int latency = 80;
if (latency < 1000) {
System.out.println("1초 미만");
} else if (latency < 100) {
System.out.println("100ms 미만");
}
80은 두 조건을 모두 만족하지만 첫 번째 조건에서 이미 실행이 끝나므로 100ms 미만은 출력되지 않는다.
더 구체적인 조건을 먼저 두는 방식이 자연스럽다.
if (latency < 100) {
System.out.println("매우 빠름");
} else if (latency < 1000) {
System.out.println("보통");
} else {
System.out.println("느림");
}
사용자에게 여러 혜택이 동시에 적용될 수 있다고 해보자.
int discount = 0;
if (isNewUser) {
discount += 1000;
}
if (hasCoupon) {
discount += 2000;
}
두 조건이 동시에 참이면 두 할인 모두 적용된다.
이를 else if로 바꾸면 첫 번째 조건이 참인 순간 두 번째 혜택은 검사조차 하지 않는다. 조건문을 고를 때는 서로 배타적인 선택인지, 동시에 적용 가능한 독립 조건인지부터 판단해야 한다.
switch의 fall-through를 직접 이해하기int level = 2;
switch (level) {
case 1:
System.out.println("BASIC");
case 2:
System.out.println("PRO");
case 3:
System.out.println("ENTERPRISE");
}
level이 2라면 PRO뿐 아니라 그 아래 ENTERPRISE까지 실행된다. 이것이 fall-through다.
의도한 동작이 아니라면 break가 필요하다.
case 2:
System.out.println("PRO");
break;
현대적인 화살표 switch는 기본적으로 이런 fall-through가 없어 실수가 줄어든다.
String label = switch (httpStatus) {
case 200 -> "SUCCESS";
case 400 -> "BAD_REQUEST";
case 404 -> "NOT_FOUND";
default -> "UNKNOWN";
};
과거에는 변수를 먼저 만들고 각 case에서 값을 대입해야 했지만, 이제는 분기의 결과 자체를 값으로 만들 수 있다.
String badge = score >= 80 ? "PASS" : "RETRY";
이 정도는 읽기 쉽다.
하지만 삼항 연산자를 중첩하면 빠르게 복잡해진다.
String result = a ? b ? "X" : "Y" : "Z";
조건이 복잡하거나 실행해야 할 문장이 여러 개라면 if문으로 풀어 쓰는 편이 낫다.
조건식이 예상과 다르게 동작하면 한 번에 전체 식만 보지 말고 부분 결과를 확인한다.
boolean enoughStock = stock > 0;
boolean allowedRegion = region.equals("KR");
System.out.println("enoughStock=" + enoughStock);
System.out.println("allowedRegion=" + allowedRegion);
if (enoughStock && allowedRegion) {
// ...
}
복합 조건을 작은 불린 값으로 나누면 논리가 훨씬 쉽게 보인다.
if는 조건이 참일 때 특정 코드를 실행한다.if-else는 두 갈래 분기에 적합하다.else if는 여러 조건 중 처음으로 참인 하나의 경로를 선택한다.if를 사용한다.switch가 더 읽기 좋을 수 있다.switch 표현식은 -> 문법으로 값을 반환할 수 있다.