Study/Java

[Java] 조건문

the.Dev.Cat 2026. 4. 4. 07:15
Java 입문 — 조건문

김영한의 자바 입문 강의 내용을 정리한 글이다.

1. 조건문이란

지금까지 살펴본 프로그램은 위에서 아래로 한 줄씩 순서대로 실행됐다. 그런데 실제 프로그램은 상황에 따라 다른 경로로 흘러야 한다. 로그인 성공/실패, 나이에 따른 접근 제어, 구매 금액에 따른 할인 적용처럼 특정 조건이 참일 때만 특정 코드를 실행해야 하는 상황이 수없이 등장한다.

자바는 이를 위해 두 가지 조건문을 제공한다.

구문용도
if / else if / else범위 조건, 복합 조건식
switch특정 값과의 동등 비교

2. if문

기본 구조

if (condition) { // 조건이 true일 때 실행 }

condition 자리에는 boolean 타입으로 평가되는 식이 와야 한다. true이면 블록 안 코드를 실행하고, false이면 건너뛴다. {} 사이의 코드를 코드 블록이라 한다.

int age = 20; if (age >= 18) { System.out.println("성인입니다."); } if (age < 18) { System.out.println("미성년자입니다."); }

age = 20이므로 첫 번째 if는 true, 두 번째 if는 false가 된다. "성인입니다."만 출력된다.

조건이 참으로 평가되는 과정을 단계별로 풀어보면 다음과 같다.

if (age >= 18) // age = 20 if (20 >= 18) // true { "성인입니다." 출력 }
조건 검사 if (age >= 18) false true 건너뜀 블록 실행

else문

elseif 조건이 거짓일 때 실행할 코드를 제공한다. 서로 반대되는 두 경우를 표현할 때 if 두 개보다 if-else가 의도를 더 명확하게 드러낸다.

if (age >= 18) { System.out.println("성인입니다."); } else { System.out.println("미성년자입니다."); }

두 if를 독립적으로 쓰면 조건을 두 번 검사한다. if-else는 조건을 한 번만 검사하고, 둘 중 하나만 실행된다는 의미를 코드 자체로 표현한다.


3. else if

독립 if의 문제점

연령대를 분류하는 코드를 독립 if로 작성하면 다음과 같다.

int age = 14; if (age <= 7) { System.out.println("미취학"); } if (age >= 8 && age <= 13) { System.out.println("초등학생"); } if (age >= 14 && age <= 16) { System.out.println("중학생"); } if (age >= 17 && age <= 19) { System.out.println("고등학생"); } if (age >= 20) { System.out.println("성인"); }

이 코드에는 두 가지 문제가 있다.

  • 불필요한 조건 검사: age = 5라면 첫 번째 if에서 이미 결과가 나온다. 그런데 남은 4개의 if도 모두 검사한다.
  • 중복 조건: 초등학생 블록에서 age >= 8을 검사한다. 그런데 앞의 if에서 age <= 7이 거짓이라는 것을 이미 확인했으므로, 이 시점의 age는 이미 8 이상이다. 같은 정보를 두 번 확인하는 것이다.

else if 사용

if (age <= 7) { System.out.println("미취학"); } else if (age <= 13) { System.out.println("초등학생"); } else if (age <= 16) { System.out.println("중학생"); } else if (age <= 19) { System.out.println("고등학생"); } else { System.out.println("성인"); }

else if는 앞선 조건이 거짓일 때만 다음 조건을 검사한다. age <= 7이 거짓이라면 이미 age > 7이 보장되므로, 다음 조건에서 age >= 8을 다시 쓸 필요가 없다. 전체 if-else if-else 블록에서 정확히 하나의 분기만 실행된다.

if (age <= 7) false else if (age <= 13) false else if (age <= 16) false else if (age <= 19) false else true 미취학 true 초등학생 true 중학생 true 고등학생 성인

독립 if와 else if의 선택 기준

조건들이 서로 연관되어 하나만 실행되어야 한다면 else if를 사용한다. 조건들이 독립적으로 모두 적용될 수 있다면 독립 if를 사용한다.

int price = 10000; int age = 10; int discount = 0; if (price >= 10000) { discount += 1000; System.out.println("10000원 이상 구매, 1000원 할인"); } if (age <= 10) { discount += 1000; System.out.println("어린이 1000원 할인"); } System.out.println("총 할인 금액: " + discount + "원"); // 2000원

두 조건을 else if로 연결하면 첫 번째 조건이 참일 때 두 번째 할인이 적용되지 않는다. 두 할인은 서로 독립적이므로 각각 별도의 if로 검사해야 한다.


4. 중괄호 생략

if문 다음에 실행할 문장이 하나뿐이면 중괄호를 생략할 수 있다.

if (true) System.out.println("실행됨");

그런데 이 패턴은 버그를 유발하기 쉽다. 다음 코드를 보자.

if (true) System.out.println("if 내부"); System.out.println("if와 무관"); // 항상 실행된다

들여쓰기가 if 블록 안에 있는 것처럼 보이지만, 두 번째 println은 if와 아무 관계가 없다. 중괄호 없이는 if 바로 다음 문장 하나만 블록으로 취급된다. 중괄호를 쓰면 이 혼동이 사라진다.

if (true) { System.out.println("if 내부"); System.out.println("이것도 if 내부"); }

Google Java Style, Oracle Java Code Conventions 등 주요 코드 스타일 가이드는 예외 없이 중괄호 사용을 권장한다. 문장이 하나여도 중괄호를 사용하는 습관이 가독성과 유지보수 안전성 모두에 유리하다.


5. switch문

기본 구조

switch (조건식) { case value1: // 조건식 == value1일 때 break; case value2: // 조건식 == value2일 때 break; default: // 어떤 case도 일치하지 않을 때 }

switchif와 달리 동등 비교(==)만 수행한다. age > 18 같은 범위 조건은 switch로 표현할 수 없다. 반면 특정 값에 따라 분기하는 경우라면 switch가 if-else보다 읽기 쉽다.

break와 fall-through

break는 현재 실행 중인 switch 블록을 빠져나간다. break가 없으면 일치한 case 이후의 모든 case가 순서대로 실행된다. 이것을 fall-through라 한다.

int grade = 2; int coupon; switch (grade) { case 1: coupon = 1000; break; case 2: // break 없음 — fall-through 발생 case 3: coupon = 3000; break; default: coupon = 500; } System.out.println("발급받은 쿠폰 " + coupon); // 3000

grade = 2이면 case 2에서 시작한다. break가 없으므로 case 3coupon = 3000까지 실행된다. "2등급과 3등급은 같은 쿠폰"이라는 요구사항을 간결하게 표현하는 의도적 fall-through다. 단, 우발적인 fall-through는 찾기 어려운 버그의 원인이 된다.

switch (grade) case 1 case 2 case 3 default fall-through coupon = 3000 coupon = 1000 coupon = 500

grade = 2이면 case 2에서 시작해 break 없이 case 3으로 이어진다.

if vs switch 선택 기준

비교 항목if-elseswitch
조건 표현력범위(>), 복합(&&, ||) 모두 가능동등 비교만 가능
타입모든 타입int, char, String, enum
가독성복잡한 조건에 유리특정 값 분기에 유리
성능조건 수에 비례 O(n)tableswitch O(1), lookupswitch O(log n)

JVM은 switch를 컴파일할 때 두 가지 바이트코드 명령으로 최적화한다. case 값이 연속적이면 tableswitch(점프 테이블, O(1)), 띄엄띄엄 있으면 lookupswitch(이진 탐색, O(log n))를 사용한다. case가 많을수록 if-else 대비 switch의 성능 이점이 커진다.

Java 14 switch 표현식

Java 14부터 switch가 표현식(expression)으로도 사용 가능해졌다. 기존 switch문과의 핵심 차이는 두 가지다.

  • -> 화살표 문법으로 fall-through가 없다
  • switch 전체가 값을 반환할 수 있다
int grade = 2; int coupon = switch (grade) { case 1 -> 1000; case 2 -> 2000; case 3 -> 3000; default -> 500; }; System.out.println("발급받은 쿠폰 " + coupon); // 2000

break 없이도 fall-through가 발생하지 않고, 결과를 변수에 바로 대입할 수 있다. Java 14 이후 새로 작성하는 코드라면 switch 표현식 형태를 우선 고려하는 것이 좋다.


6. 삼항 연산자

구조

(조건) ? 참_표현식 : 거짓_표현식

항(operand)이 3개이므로 삼항(ternary) 연산자라 한다. 자바에서 유일하게 항이 3개인 연산자다. 조건 연산자(conditional operator)라고도 부른다. 조건에 만족하면 참_표현식이, 조건에 만족하지 않으면 거짓_표현식이 실행된다.

if-else와의 비교

// if-else 방식 String status; if (age >= 18) { status = "성인"; } else { status = "미성년자"; } // 삼항 연산자 String status = (age >= 18) ? "성인" : "미성년자";

두 코드는 동일하게 작동한다. JVM 바이트코드 수준에서도 성능 차이가 없다. 삼항 연산자는 단순히 두 값 중 하나를 선택할 때 코드를 간결하게 만든다.

// 적합한 사용 예 int max = (a > b) ? a : b; String result = (x % 2 == 0) ? "짝수" : "홀수"; // 중첩 삼항 — 읽기 어렵다, else if가 낫다 String grade = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "F";

중첩 삼항 연산자는 기술적으로 가능하지만, 읽는 사람이 파악하기 어렵다. 두 단계 이상 중첩이 필요하다면 else if로 풀어쓰는 것이 더 명확하다.


7. 조건문 선택 정리

조건 분기가 필요하다 단순히 두 값 중 하나 선택? YES 삼항 연산자 a > b ? a : b NO 특정 값과의 동등 비교? YES switch문 case / -> NO if-else if-else 범위·복합 조건

조건문은 코드의 흐름을 제어하는 가장 기본적인 도구다. if와 switch 어느 것을 사용해도 동작은 같다. 차이는 의도를 얼마나 명확하게 드러내느냐에 있다.