본문 바로가기

Java/문법

[Java] enum(열거형) - 정의, 문법, 사용 예제, 실제 사례

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문과 메소드가 계속 추가되어야 한다.

enum 결제방식

코드 설명
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()을 호출하면 "계좌이체" 라는 문자열이 반환됩니다.)

여러 개의 PayType을 '그룹화'하여 관리하고, 특정 결제 타입이 어느 그룹에 속하는지 찾는 기능을 제공

코드 설명
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);

 

 


프로젝트

 

참고자료

반응형