enum이 뭐야? 왜 써야 돼?
💡상수의 집합
- enum은 상수의 집합을 나타냅니다.
- 관련된 상수들을 논리적으로 그룹화할 수 있습니다.
💡가독성, 타입 안정성, 관련 메소드 정의
- 가독성: 상수 그룹을 하나의 타입으로 묶어 의미를 명확히 표현할 수 있습니다.
- 타입 안정성: 잘못된 값을 사용할 가능성을 줄이고, 컴파일 타임에 오류를 발견할 수 있습니다.
- 관련 메소드 정의: 관련 메소드나 필드를 함께 정의할 수 있어서, 코드의 응집도를 높일 수 있습니다.
enum 문법
public enum EnumName {
CONSTANT1,
CONSTANT2,
CONSTANT3;
}
enum 사용 예제1
- 다음은 enum을 사용하여 요일을 나타내는 예제입니다.
- Day라는 enum을 정의하고 그 안에 일주일의 요일을 상숭로 선언했습니다.
- Main에서는 swith문을 사용하여 각 요일에 대한 다른 행동을 정의합니다.
- Day.SUNDAY를 MONDAY로 바꾼다면? Today is Monday가 출력됩니다.
- case에 없는 WEDNESDAY로 바꾼다면? defulat인 ...이 출력됩니다.
public enum Day {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
}
import java.time.DayOfWeek;
import java.time.LocalDate;
public class Main {
public static void main(String[] args) {
Day today = Day.SUNDAY;
switch (today) {
case MONDAY:
System.out.println("Today is Monday");
break;
case TUESDAY:
System.out.println("Today is Tuesday");
break;
case SUNDAY:
System.out.println("Today is Sunday");
break;
default:
System.out.println("...");
}
}
}
// Today is Sunday
enum 사용 예제2
- enum은 필드와 메서드를 가질 수 있습니다.
- 각 요일에 대응하는 한글 이름을 필드로 추가하고, 이를 반환하는 메소드를 추가하였습니다.
- 필드: private final String name
- 생성자: Day(String name) {
this.name = name;
} - 메서드: public String getName() {
return name;
}
public enum Day {
SUNDAY("일요일"),
MONDAY("월요일"),
TUESDAY("화요일"),
WEDNESDAY("수요일"),
THURSDAY("목요일"),
FRIDAY("금요일"),
SATURDAY("토요일");
// 필드
private final String name;
// 생성자
Day(String name) {
this.name = name;
}
// 메서드
public String getName() {
return name;
}
}
public class Main {
public static void main(String[] args) {
Day today = Day.WEDNESDAY;
System.out.println("오늘은 " + today.getName() + "입니다.");
}
}
// 오늘은 수요일입니다.
실제 사례 (배달의 민족 Java Enum 활용기)
- 결제된 건이 어느 결제 종류에 속하는지 분류할 때 '문자열 + 메소드 + if문' 조합의 기존 방식은 다음과 같은 문제가 있었습니다.
- 문제점 1. 입력값과 결과값을 예측하기 어렵다.
- 결제 수단의 범위를 지정할 수 없어서 문자열이면 전부 파라미터로 전달될 수 있다.
- 결과를 받는쪽에서도 문자열을 받기에 결제종류로 지정된 값만 받을 수 있도록 검증코드가 필요하다.
- 문제점 2. 그룹별 기능을 추가하기 어렵다.
- 결제 종류에 따라 추가 기능이 필요할 경우, 또다시 결제종류에 따른 if문 메소드가 필요하다.
- 결제 종류를 기준으로 하는 print 기능과 push하는 기능이 필요할 경우, 문자열 및 테이블 조합은 if문과 메소드가 계속 추가되어야 한다.
- 문제점 1. 입력값과 결과값을 예측하기 어렵다.
코드 설명
1. enum Type 선언
2. PayType 상수들: ACCOUNT_TRANSFER("계좌이체"), ..., EMPTY("없음") // 결제 방식이 없음을 나타내는 상수
3. 필드: title, 각 상수의 한글 표현을 저장합니다.
4. 생성자: enum 상수에 대해 생성자가 호출될 때마다 그 상수에 연결된 title 값을 설정합니다.
(ex: ACCOUNT_TRANSFER("계좌이체") 상수가 생성될 때, "계좌이체" 라는 문자열이 title 필드에 저장됩니다.)
5. 메소드: getTitle(), 각 상수에 설정된 title 값을 반환하는 메소드입니다.
(ex: PayType.ACCOUNT_TRANSFER.getTitle()을 호출하면 "계좌이체" 라는 문자열이 반환됩니다.)
코드 설명
1. enum PayGroupAdvanced 선언
2. PayGroupAdvanced 상수들: CASH, ..., EMPTY("없음", Collections.EMPTY_LIST) // Empty: 그룹이 없음을 뜻하며 여기에 속한 결제 타입은 없습니다.
3. 필드 title, payList
- title: 그룹의 이름(한글 표현)을 저장합니다.
- payList: 이 그룹에 속한 결제 타입들의 목록을 저장합니다.
4. 생성자 PayGroupAdvanced(String title, List<PayType> payList): 각 그룹에 대해 생성자가 호출될 때, 그룹의 이름과 결제 타입 목록을 설정합니다.
(ex: CASH그룹의 경우, '현금'이라는 문자열과 그에 속한 결제 타입을 포함하는 리스트가 설정됩니다.)
5. 메소드 findByPayType(PayType payType): 주어진 PayType이 속하는 그룹을 찾아 반환하는 메소드입니다.
이 메소드는 모든 PayGroupAdvanced 값을 순회하며, 각 그룹에 payType이 속해 있는지 확인합니다.
만약 속해 있다면 해당 그룹을 반환하고, 그렇지 않으면 Empty를 반환합니다.
6. 메소드 hasPayCode(PayType payType): 현재 그룹(this)의 payList에서 주어진 payType이 포함되어 있는지 확인하는 메소드입니다.
payList를 순회하며 주어진 payType이 존재하는지 확인하고, 존재하면 true, 그렇지 않으면 false를 반환합니다.
7. 메소드 getTitle(): 그룹의 이름을 반환하는 메소드입니다. 이 메소드를 통해 각 그룹의 한글 이름을 얻을 수 있습니다.
// PayGroupAdvanced.findByPayType(PayType.TOSS)를 호출하면, TOSS가 CASH 그룹에 속해 있기 때문에 CASH가 반환됩니다.
// PayGroupAdvanced.CASH.getTitle()를 호출하면 "현금"이라는 문자열이 반환됩니다.
- Java의 enum은 결국 클래스인 점을 이용하여 enum 상수에 결제종류 문자열 리스트로 갖도록 하였습니다.
- 각 enum 상수들은 본인들이 갖고 있는 문자열들을 확인하여 문자열 인자값이 어느 enum 상수에 포함되어 있는지 확인할 수 있습니다.
backend-1st-studycafe에서는 enum을 어떻게 사용했을까?
package com.example.common;
import lombok.Getter;
@Getter
public enum SeatType {
PERSON,
GROUP
}
- 스터디카페의 좌석 타입: PERSON(1인용), GROUP(단체석)을 enum으로 정의하였습니다.
- 단체석 여부 확인 if문, SeatDAO.java, Seat.java에서 사용하였습니다.
package com.example.common;
import lombok.Getter;
@Getter
public enum PriceType {
ONEHOUR("1시간", 4000),
TWOHOUR("2시간", 5000),
THREEHOUR("3시간", 6000);
// 문자열을 저장할 필드
private String time;
private Integer price;
// 생성자 (싱글톤)
private PriceType(String time, Integer price) {
this.time = time;
this.price = price;
}
public static PriceType fromTime(String time) {
for (PriceType priceType : PriceType.values()) {
if (priceType.getTime().equals(time)) {
return priceType;
}
}
throw new IllegalArgumentException("유효하지 않은 시간입니다: " + time);
}
}
- 스터디카페의 이용 요금: 다음과 같이 enum으로 그룹화하였습니다.
- 이용 시간 선택 및 가격 타입 결정, UserService.java에서 사용했습니다.
ONEHOUR("1시간", 4000),
TWOHOUR("2시간", 5000),
THREEHOUR("3시간", 6000);
프로젝트
참고자료
반응형