34. int 상수 대신 열거 타입을 사용하라
✅ 1. 문제 제기: Java에서 고정된 값(요일 등)을 int로 표현하는 건 안전할까?
🔥 문제점
public static final int MONDAY = 0;
자바는
final static int
상수를 컴파일 시 숫자 리터럴로 치환함클라이언트 코드에 숫자 자체가 직접 박힘
if (day == Constants.MONDAY) → if (day == 0)
나중에 라이브러리 쪽에서
MONDAY = 1
로 바뀌어도, 클라이언트는 여전히0
을 사용 → 의도와 다르게 동작할 위험따라서 클라이언트도 함께 다시 컴파일해야만 정상 작동함
💣 유지보수에 매우 취약한 구조
✅ 2. enum의 기본 구조와 장점
public enum Day {
MONDAY, TUESDAY;
}
🔧 자바 컴파일러는 내부적으로 이렇게 변환함:
public final class Day extends Enum<Day> {
public static final Day MONDAY = new Day("MONDAY", 0);
public static final Day TUESDAY = new Day("TUESDAY", 1);
...
}
각 상수는
public static final
객체 → 싱글톤처럼 단 하나의 인스턴스생성자는
private
이므로 외부에서 인스턴스 생성 불가상속도 불가 (
final class
) → 열거 타입은 설계가 고정됨
🌟 장점
✅ 1. 인스턴스 통제
각 상수는 클래스 내부에서 단 하나만 만들어짐 → 외부에서
new
로 추가 인스턴스 생성 불가확장 불가능 (상속 금지)
→ enum은 본질적으로 싱글톤 집합 → 설계 안정성 + 메모리 안전성
✅ 2. 컴파일 타임 타입 안정성
enum Day { MONDAY, TUESDAY }
public void doSomething(Day day) {
if (day == Day.MONDAY) { ... }
}
day
는Day
타입만 받을 수 있음"MONDAY"
(문자열)이나99
(숫자) 같은 잘못된 값은 컴파일 에러→ 타입 안정성 보장 + 오타 방지 + IDE 자동완성 가능
✅ 3. 클래스처럼 기능 확장 가능
enum은 메서드 정의, 필드 추가 가능
toString()
,values()
,valueOf()
자동 생성implements 인터페이스
도 가능→ 단순 상수를 넘어서 행위와 데이터가 함께 있는 객체처럼 사용 가능
✅ 3. 고급 기능 예시: enum은 상수 집합 그 이상이다
🎯 예시 1: 상수별 메서드 구현 (constant-specific method implementation)
public enum Operation {
PLUS { public double apply(double x, double y) { return x + y; } },
MINUS { public double apply(double x, double y) { return x - y; } };
public abstract double apply(double x, double y);
}
각 상수가
apply()
메서드를 자기 방식대로 오버라이딩switch 없이 동작 분기 가능
동작과 상수를 하나로 결합 → 코드 깔끔 & 확장성 높음
🎯 예시 2: 상수별 데이터 포함
public enum Operation {
PLUS("+"), MINUS("-");
private final String symbol;
Operation(String symbol) { this.symbol = symbol; }
@Override public String toString() { return symbol; }
}
Operation.PLUS
는"+"
라는 출력용 기호도 가짐System.out.println(Operation.PLUS)
→+
→ enum에 의미 있는 데이터와 표현력을 함께 담을 수 있음
🎯 예시 3: 전략 열거 타입 (Strategy Enum)
enum PayrollDay {
MONDAY(PayType.WEEKDAY), SATURDAY(PayType.WEEKEND);
private final PayType payType;
PayrollDay(PayType payType) { this.payType = payType; }
int pay(int mins, int rate) {
return payType.pay(mins, rate);
}
enum PayType {
WEEKDAY {
int overtimePay(int mins, int rate) {
return mins <= 480 ? 0 : (mins - 480) * rate / 2;
}
},
WEEKEND {
int overtimePay(int mins, int rate) {
return mins * rate / 2;
}
};
abstract int overtimePay(int mins, int rate);
int pay(int mins, int rate) {
return mins * rate + overtimePay(mins, rate);
}
}
}
✅ 전략 열거 타입의 장점
상수별 전략(행동)을 별도로 분리해 관리 가능
switch
없이 요일마다 다른 급여 계산 로직 처리 가능기존 enum 수정 없이 전략만 확장하면 됨 → 높은 유지보수성
✅ 4. switch문은 정말 안 써야 할까?
enum의 상수별 동작을 위해선 상수별 메서드 구현이나 전략 열거 타입이 일반적으로 좋지만, 단순히 외부 기능을 추가하고 싶다면 switch도 괜찮음.
public static Operation inverse(Operation op) {
switch (op) {
case PLUS: return Operation.MINUS;
case MINUS: return Operation.PLUS;
default: throw new AssertionError(op);
}
}
✅ 5. 언제 enum을 쓰면 좋을까?
☑️ 컴파일 타임에 상수 집합이 정해져 있다면 → enum이 최적의 선택!
요일, 성별
✅ 매우 적합
행성, 체스 말
✅ 매우 적합
메뉴 옵션, 명령 플래그
✅ 매우 적합
사용자 ID, 채팅 메시지 등 동적 데이터
❌ 부적합
✅ 6. 마무리
자바의 enum은 단순한 상수 묶음이 아닙니다. 행동과 데이터를 함께 가질 수 있는 강력한 타입이며, 코드의 안전성과 가독성을 높이고, 잘못된 값이나 구조 변경에 강한 안정성과 확장성을 제공합니다.
고정된 상수 집합이 필요할 땐, enum이 가장 안전한 선택입니다.
발표자료
https://byumm315.atlassian.net/wiki/external/YzI0ZmQ2ZDViODRlNDViZjhhYmU2ZDYyZWI0OWZmZTg
Last updated