1. 소개
프로그래밍에서는 미리 정해진 제한된 선택지의 목록을 다루는 일이 많습니다. 예: 요일, 신호등 색, 게임 난이도, 주문 상태. 이런 선택지는 보통 고정된 값으로 표현됩니다. 바로 여기서 오늘의 주제인 열거형(enum)과 맞닿습니다.
열거형은 이름이 붙은 상수 집합을 선언할 수 있게 해 주는 특별한 데이터 타입입니다.
enum은 칸칸이 분류된 상자에 라벨을 붙여 둔 것과 같습니다. 각 라벨은 어떤 숫자에 연결된 고유한 이름입니다.
enum의 주요 장점:
- 코드가 더 읽기 쉽고 자체 문서화됩니다;
- 0, 1, 2 같은 "매직 넘버" 대신 DayOfWeek.MONDAY나 TrafficLight.RED처럼 의미 있는 이름을 사용합니다;
- 잘못된 값을 대입하려 하면 컴파일러가 오류를 알려 줍니다;
- 각 요소 뒤에는 사실… 평범한 정수가 있습니다! (이 부분은 뒤에서 다시 다룹니다.)
enum 선언 문법
// 열거형 선언의 일반 템플릿
public enum Imya
{
KONSTANTA1 ,
KONSTANTA2 ,
KONSTANTA3
}
Java에서 열거형을 선언하는 것은 매우 쉽습니다. 기본 예시는 다음과 같습니다:
// 파일 DayOfWeek.java
public enum DayOfWeek {
MONDAY, // 0
TUESDAY, // 1
WEDNESDAY, // 2
THURSDAY, // 3
FRIDAY, // 4
SATURDAY, // 5
SUNDAY // 6
}
설명:
- 키워드 enum은 컴파일러에게 "이건 열거형이다!"라고 알려 줍니다.
- 중괄호 안에는 쉼표로 구분된 값 이름(상수)들이 옵니다.
- 이름은 보통 UPPER_SNAKE_CASE(모두 대문자, 단어 사이에 밑줄)로 작성합니다.
enum은 어디에 선언할 수 있을까요?
- 별도의 파일(DayOfWeek.java)에서.
- 클래스 내부(해당 클래스만을 위한 private 열거형이 필요할 때).
- 메서드 내부에서도 가능하지만, 자주 쓰이진 않습니다.
2. 코드에서 enum 사용
enum 변수 선언:
DayOfWeek today = DayOfWeek.MONDAY;
이제 today에는 DayOfWeek에 선언된 값들만 대입할 수 있습니다.
switch에서의 사용 예
switch (today)
{
case MONDAY:
System.out.println("아, 월요일...");
break;
case FRIDAY:
System.out.println("야호, 금요일!");
break;
default:
System.out.println("평범한 날.");
}
중요한 차이점: case에서는 변수의 타입을 컴파일러가 이미 알고 있다면 접두사 없이 상수 이름만 적습니다.
모든 enum 값 순회
모든 enum에는 values()라는 정적 메서드가 있어, 모든 값을 담은 배열을 반환합니다:
for (DayOfWeek day : DayOfWeek.values())
{
System.out.println(day);
}
메뉴 표시, 검증, 후보 생성 등에 아주 유용합니다.
3. enum 메서드: name(), ordinal(), valueOf()
Java의 열거형은 단순한 상수 목록이 아니라 메서드를 가진 온전한 클래스입니다!
name() 메서드
코드에 작성된 그대로의 상수 이름을 문자열로 반환합니다:
DayOfWeek day = DayOfWeek.FRIDAY;
System.out.println(day.name()); // "FRIDAY"
ordinal() 메서드
상수의 순번(0부터 시작)을 반환합니다:
System.out.println(DayOfWeek.MONDAY.ordinal()); // 0
System.out.println(DayOfWeek.FRIDAY.ordinal()); // 4
주의: 나중에 순서가 바뀔 수 있다면 ordinal() 값으로 저장하거나 비교하지 마세요! 이름을 사용하는 것이 좋습니다.
valueOf(String name) 메서드
문자열을 해당 enum 값으로 변환합니다(해당 상수가 존재할 경우):
DayOfWeek day = DayOfWeek.valueOf("MONDAY");
System.out.println(day); // MONDAY
일치하는 상수가 없으면 IllegalArgumentException이 발생합니다.
values() 메서드
모든 enum 값의 배열을 반환합니다(위에서 이미 예시를 보았습니다):
DayOfWeek[] days = DayOfWeek.values();
4. 필드, 생성자, 메서드를 가진 enum
Java의 열거형은 확장할 수 있습니다: 필드, 생성자, 메서드를 추가할 수 있어요! 단순한 이름 목록이 아니라 작은 클래스라고 생각하면 됩니다.
예: 현지화된 요일 이름
public enum DayOfWeek
{
MONDAY("Ponedel’nik"),
TUESDAY("Vtornik"),
WEDNESDAY("Sreda"),
THURSDAY("Chetverg"),
FRIDAY("Pyatnitsa"),
SATURDAY("Subbota"),
SUNDAY("Voskresen’e");
private final String russianName;
// 생성자(기본적으로 private)
DayOfWeek(String russianName)
{
this.russianName = russianName;
}
public String getRussianName()
{
return russianName;
}
}
이게 어떻게 동작하는지는 27레벨 이후 OOP를 배울 때 더 자세히 알아봅니다 :P
이제 이렇게 사용할 수 있습니다:
DayOfWeek day = DayOfWeek.WEDNESDAY;
System.out.println(day.getRussianName()); // "Sreda"
포인트: 각 enum 값은 자신의 데이터를 가질 수 있습니다(이 경우 — 러시아어 이름).
enum 사용의 장점
- 타입 안전성: 열거형에 없는 값을 실수로 대입할 수 없습니다.
- 가독성: 코드가 스스로를 설명합니다(TrafficLight.RED vs 1 또는 "red").
- 유지보수 용이성: 항목을 추가/삭제해야 할 때 한 곳만 수정하면 됩니다.
- switch와 잘 작동: enum은 값에 따라 분기하는 데 최적입니다.
- 확장 가능: 필드와 메서드를 추가하고 인터페이스도 구현할 수 있습니다.
- 오류 감소: 컴파일러가 경우를 빠뜨리지 않도록 도와줍니다(특히 switch 구문에서).
6. 실습: 우리 애플리케이션에 enum 사용하기
우리의 미니 애플리케이션에 enum을 이용한 요일 지원을 추가해 봅시다.
1단계. enum 선언
public enum DayOfWeek
{
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
2단계. 코드에서 사용
System.out.println("요일을 입력하세요(예: MONDAY):");
Scanner console = new Scanner(System.in);
String input = console.nextLine().toUpperCase();
DayOfWeek day = DayOfWeek.valueOf(input);
switch (day)
{
case MONDAY:
System.out.println("업무 주의 시작!");
break;
case FRIDAY:
System.out.println("곧 주말!");
break;
case SATURDAY:
case SUNDAY:
System.out.println("와, 주말이다!");
break;
default:
System.out.println("평범한 근무일.");
}
동작 설명:
- 사용자가 요일을 입력합니다(예: "monday" 또는 "MONDAY").
- 대소문자에 영향을 받지 않도록 문자열을 대문자로 변환합니다(toUpperCase()).
- valueOf로 문자열을 enum 값으로 변환합니다.
- switch로 서로 다른 메시지를 출력합니다.
- 잘못된 입력이면 예외를 잡아 경고를 출력합니다.
7. enum 사용 시 흔한 실수
오류 №1: enum 대신 문자열이나 숫자를 사용함. 초보자는 종종 이렇게 작성합니다:
int day = 1; // 1이 월요일인가요?
또는
String status = "DELIVERED";
좋지 않습니다: 철자가 틀릴 수 있고 유지보수가 어렵습니다. enum을 사용하세요!
오류 №2: ==와 .equals()로 enum 비교. Java에서는 enum 값을 ==로 비교해도 안전합니다. 각 값이 해당 enum 클래스 내에서 유일하기 때문입니다:
if (day == DayOfWeek.MONDAY) { ... } // OK!
.equals()도 동작하지만, 보통은 ==를 더 자주 사용합니다.
오류 №3: 열거형 항목의 나쁜 이름. 요소 이름을 VALUE1, VALUE2, VALUE3처럼 짓지 마세요 — 한 달 뒤엔 아무도 그 의미를 모릅니다! 의미 있는 이름을 사용하세요.
오류 №4: 로직에 ordinal()을 사용함. 이렇게 작성하지 마세요:
if (day.ordinal() == 0) { ... } // 그러지 마세요!
요소 순서는 바뀔 수 있으며, 그러면 모든 것이 망가집니다. 이름을 사용하세요!
GO TO FULL VERSION