조종 다음은 개발
article thumbnail

서론

우테코 프리코스 2 주차 미션 완료 이후, 피드백에서 객체에서 상수를 관리하는 방법 대신 Enum을 활용해 보는 것을 추천받았었다.

이름은 혹시 모르니 모자이크 했다.

나도 Enum 을 알고 있지만 굳이 왜 사용해야하는지 이해가 안 됐다.

만약 위의 ErrorMessage를 Enum으로 만들었다면 아래와 같은 차이점이 있을 것이다.

throw new IllegalArgumentException(ErrorMessage.INPUT_BLANK.getMessage())

Enum을 활용한 버전

throw new IllegalArgumentException(ErrorMessage.INPUT_BLANK)

객체를 활용한 버전

 

나는 객체를 사용한 버전이 훨씬 간단하고 깔끔한 것 같다.

그래서 그런지 나는 왜 Enum 을 사용해야 하는지 이해가 안 되었다.

그래서 이번기회에 Enum을 사용하면 어떤 이점이 있는지 한 번 알아보았다.

Enum에 대해

🧐 Enum 이란?

Enum 은 열거형 타입의 클래스이다.
서로 연관 있는 상수를 편하게 다루기 위해 사용한다.
(예 : 요일, 등급, 색깔 등등)와 같이 비슷한 성격을 가진 상수들을 Enum으로 만들면 아래와 같이 바꿀 수 있다.

class CardType { 
    static final int CLOVER = 0; 
    static final int HEART = 1; 
    static final int DIAMOND = 2; 
    static final int SPACE = 3; }

상수로 사용한 버전

public enum CardType { 
    CLOVER(0), HEART(1), DIAMOND(2), SPACE(3); 

    private final int value; 

    CardType(int value) { 
        this.value = value; 
    } 
}

Enum을 사용한 버전

  • Enum 은 일종의 클래스로 상수 하나당 인스턴스를 하나씩 만들어서 public static final 필드로 제공한다.
  • 따라서 위와 같이 CarType.CLOVER로 접근할 수 있다. 이런 특징으로 싱글톤 객체인 것을 알 수 있다.
  • System.out.println(CardType.CLOVER) // CLOVER

🎯 주요 메서드

메소드 설명
static E values() 해당 열거체의 모든 상수를 저장한 배열을 생성하여 반환
static E valueOf(String name) 전달된 문자열과 일치하는 해당 열거체의 상수를 반환함
protected void finalize() 해당 Enum 클래스가 final 메소드를 가질 수 없게 함
String name() 해당 열거체 상수의 이름 반환
int ordinal() 해당 열거체 상수가 열거체 정의에서 정의된 순서 반환
boolean equals(Object other) 객체가 해당 열거체 상수와 동일하면 true

👍 Enum의 장점

안전한 타입 체크

public enum Value {
    ONE(1), TWO(2), THREE(3);

    private final int value;

    Value(int value) {
        this.value = value;
    }
}

위와 같은 Enum 이 추가로 있을 때

if (CardType.HEART == Value.ONE) // 컴파일 에러. 값은 같지만 타입이 다름

이처럼 값뿐만 아니라 타입까지 체크하기 때문에 타입에 안전하다.

만약 잘못된 경우 컴파일 단계에서 에러가 발생하기 때문에 쉽게 문제점을 파악할 수 있다.

빠른 비교 가능

enum Direction {EAST, SOUTH, WEST, NORTH};
if (dir == Direction.EAST){
    ...
} else if (dir > Direction.WEST) { // 에러. 열거형 상수에 비교연산자 사용불가
    ...
} else if (dir.compareTo(Direction.WEST) > 0) { // compareTo 는 가능
    ...
}
  • equals 대신 == 를 통한 비교가 가능하다. 그만큼 빠른 성능을 제공한다는 의미
  • 비교 연산자는 사용 불가능하다
  • compareTo 를 사용한 비교는 가능하다.
    • 왼쪽이 크면 양수
    • 값이 같으면 0
    • 오른쪽이 크면 음수

switch 문

switch (dir) {
    case EAST: x++; // Direction.EAST 라고 쓰면 안된다.
        break;
    case WEST : y++;
        break;
    ...
}
  • case 문에 열거형의 이름은 적지 않고 상수의 이름만 적어야 한다.
  • 간결하고 가독성이 좋아진다.

🧐 그래서 Enum을 사용해야 돼?? 

지금까지 Enum에 대해 알아보았다.
이제 다시 처음으로 돌아가서 생각해 보자.
Enum을 사용해야 할까??

 

나의 결론은 서로 연관된 상수인 경우는 Yes, 그렇지 않은 경우는 보류이다.


등급이나 계급과 같이 서로 연관성이 있는 상수들은 서로 비교하는 등의 작업을 자주 수행할 가능성이 높다.
이럴 경우에는 Enum을 활용하는 것이 좋은 선택지가 될 것 같다.

 

반면, 서로 연관성이 별로 없는 경우는 Enum의 장점을 잘 활용할 수 없다.
물론 Enum을 활용하면 예약어(pulbic staic final String)를 생략할 수 있는 장점이 있다.

enum ErrorMessage {

    INPUT_BLANK("빈 값을 입력하였습니다."),
    INPUT_NOT_INTEGER("숫자를 입력해야합니다."),
    INVALID_CAR_NAME("자동차 이름은 5자 이하 이여야합니다."),
    INVALID_NEGATIVE("0 보다 작은 값을 입력할 수 없습니다.");

    private final String message;

    ErrorMessage(String message) {
        this.message = message;
    }

    @Override
    public String toString() {
        return this.message;
    }
}

위와 같이 예약어를 생략할 수 있다.

 

그러나 이러한 장점보다는 상수로 이루어진 객체를 사용해서 문자열을 간단히 사용할 수 있는 이점이 더 큰 것 같다.

나의 지식의 깊이가 얕기 때문에 이러한 결론으로 도달한 것일 수 도 있다.

앞으로 더 알아보면서 생각이 바뀐다면 글을 수정해야겠다.


(댓글로 Enum을 활용해야 하는 이유에 대해 첨언해 주시면 감사하겠습니다)

profile

조종 다음은 개발

@타칸

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!