본문 바로가기
Java

[Java / enum] - 왜 enum이 상수 클래스보다 더 좋은건데??

by zangsu_ 2023. 11. 15.

서론

안녕하세요, 우테코 6기 백엔드 지원자 Zangsu 입니다!
우선, 글을 작성하기 전 미리 말씀 드리자면, 저는 대부분의 상수를 별도의 클래스를 생성해 관리하고 있었는데요.

그 이유는 다음과 같습니다.

1. 열거형은 하나의 논리적인 그룹에 포함되는 값들을 열거하기 위해 사용해야 한다.
모든 상수를 하나의 'enum'에 몰아 둔다면, 서로 관심사가 어중간하게 다른 값들이 하나의 "열거형" 이라는 그룹에 위치하게 되는데, 이는 올바른 책임 분리라고 생각하지 않았습니다.

2. 'enum'을 사용하게 되면 상수 클래스에 비해 값을 가지고 오는 코드가 길어진다.
이건 정말 사소한 취향인데요.
상수 클래스를 사용한다면 값을 가지고 오는 코드는 다음과 같을겁니다.
'ClassName.constName'
반면, 'enum'을 사용해 관리하게 되면 코드는 다음과 같죠.
'EnumName.constName.getValue()' / 'EnumName.constName.fieldName'
특정 기능 (값을 가져온다.)을 위한 코드가 과하게 길어진다면, 이 역시 가독성에 영향을 준다고 생각했어요.

 

그럼, 왜 상수를 'enum'으로 관리하는게 좋은걸까?

그럼에도, 'enum'이 가지는 장점 또한 명확한데요.
이미 많은 분들이 "'enum'은 싱글턴으로 관리된다.", "'enum'에는 메서드 구현이 가능하다." 등 좋은 의견을 많이 남겨 주셨습니다. 
이와 함께, 이번에 소개드리고 싶은 장점은 바로 "'enum'은 그 자체로 파라미터에 제약을 줄 수 있다." 라는 것입니다.

그리고, 이 장점을 간단한 예시와 함께 설명드려 볼게요.
우리가 이번 글에서 해결할 문제는 "우테코 지원자들의 지원 파트를 입력받아 해당 지원자가 미션에서 사용해야 할 언어를 출력해 주는 것" 입니다.
조금 더 문제를 명확하게 명시해 둘게요.
우리는 다음과 같은 세 개의 입력/결과를 제공해야 해요.

  • FE 입력시 : JavaScript
  • BE 입력시 : Java
  • Android 입력시 : Kotlin

 

상수 클래스를 사용해서 구현한다면??

이제 우리는 다음과 같은 클래스를 가질 수 있을거에요.

public class InputMessage{
	public static final FRONTEND = "FE";
	public static final BACKEND = "BE";
	public static final ANDROID = "Android"
}



그리고, 우리의 비즈니스 로직은 다음과 같겠죠.

public String getOutput(String input){
    if(input.equals(InputMessage.FRONTEND)){
    	return "FE";
    }
    if(input.equals(InputMessage.BACKEND)){
    	return "BE";
    }
    if(input.equals(InputMessage.ANDROID)){
    	return "Android";
    }
    throw new IllegalArgumentException();
}


메서드에 입력된 'String'을 확인하며 적절한 출력 값을 리턴해 줄거에요.
그런데, 사실 해당 메서드를 구현한 목적은 "정해진 형식의 입력값에 대한 출력 값 리턴" 이지만, 해당 메서드가 정해진 형식의 입력값을 받아온다는 보장은 없네요.
때문에 해당 메서드는 의도하지 않은 입력값에 대해 예외를 발생시키고 있는 모습이에요.

 

'enum'으로 구현한다면?

이번엔 'enum'으로 구현해 볼게요.

public enum InputMessage{
    FRONTEND("FE"), BACKEND("BE"), ANDROID("Android");

    private final String message;

    InputMessage(String message){
    	this.message = message;
    }
    public String getMessage(){
    	return this.message;
    }
}



이젠 우리는 다음과 같은 비즈니스 로직을 가질 수 있어요.

public String getOutput(InputMessage input){
    if(input.equals(InputMessage.FRONTEND.getMessage())){
    	return "FE";
    }
    if(input.equals(InputMessage.BACKEND.getMessage())){
    	return "BE";
    }
    if(input.equals(InputMessage.ANDROID.getMessage())){
    	return "Android";
    }
}



이제 우리는 메서드에 입력받을 'String' 타입을 'InputMessage'에 미리 정의해 둔 값들로 한정시킬 수 있어요!
(이를 위해서 외부에서 작성될 코드는 조금 더 달라지겠지만요.)
이처럼 우리는 'enum'을 사용해서 우리가 예측하는 값들만 파라미터로 받도록 제약을 걸어주고, 이를 통해 사이드 이펙트를 방지하거나 유지보수를 더 편하게 만들어 줄 수 있다고 생각해요.

+) 물론, 위의 코드는 내부에서 출력 메시지를 함께 필드로 저장하고, 해당 출력 메시지를 리턴해 주는 메서드를 추가해 주면서 더 깔끔한 코드를 만들어 줄 수도 있을거에요!
이 부분은 우리의 주요 관심사가 아니기에 최대한 위와 비슷한 형식을 유지하기 위해 적용하지 않았습니다!

결론

예시를 들어 설명하려다 보니 글이 조금 길어졌네요.
다만, 우리는 모두 프로그래머이기 때문에 글보다는 코드로 봐야 더 이해가 빠르다고 생각해 코드를 사용하는 예시를 한번 들어 봤어요.

여전히 저는 위에서 나열한 장점들에 해당하지 않는 상수들은 상수 클래스로 관리할 것 같은데요.
하지만, 'enum'의 사용이 유리한 부분에서는 적극적으로 'enum'을 사용해 보려고 해요!

 

참고가 되었던 블로그

https://sedangdang.tistory.com/240

 

상수 대신 Enum을 사용하라

* 이펙티브 자바 2/E를 읽고 공부하기 위해 기록한 게시글입니다. 30. int 상수 대신 enum을 사용하라 열거타입(enumerated type)은 고정 개수의 상수들로 값이 구성되는 자료형이다. enum 자료형이 등장하

sedangdang.tistory.com

 

'Java' 카테고리의 다른 글

상수 값 추출에 대하여  (1) 2023.12.03
[오개념 정리] Upcasting  (0) 2023.05.20

댓글