프로그래밍에서 enum은 여러 항목을 나열한 집합, 즉 미리 정의된 상수들의 묶음을 말한다. 이 글에서는 enum의 개념과 필요성 그리고 enum을 활용한 객체 지향적인 코드의 장점을 살펴보고자 한다.
문자열과 타입 안전성
자바에서 Enum Type은 왜 제공할까? 아래 예제를 통해 확인해 보자.
회원등급은 'BASIC', 'GOLD', 'DIAMOND' 총 3등급이 있다. 개발자는 회원 등급에 다른 할인율을 제공하기 위해 아래와 같은 코드를 작성했다.
public class DiscountService {
public int discount(String grade, int price) {
int discountPercent = 0;
if (grade.equals("BASIC")) {
discountPercent = 10;
} else if (grade.equals("GOLD")) {
discountPercent = 20;
} else if (grade.equals("DIAMOND")) {
discountPercent = 30;
} else {
System.out.println(grade + ":할인x");
}
return price * discountPercent / 100;
}
}
이 코드의 문제점은 무엇일까? 코드를 보면 등급이 문자열로 입력되는 것을 알 수 있다. 이는 오타가 발생하기 쉽고 유효하지 않는 값이 입력되는 문제를 초래할 수 있다. 이를 '타입 안정성이 부족하다'라고 한다. String 타입을 사용할 시 값의 제한을 할 수 없다. 'DIAMND'와 같이 잘못된 값이 입력되어도 컴파일 시 오류가 감지되지 않고 런타임에서만 문제를 발견할 수 있다.
그렇다면 문자열 상수를 사용해 보는 것은 어떨까? 상수는 미리 정의한 변수명을 사용할 수 있기 때문에 문자열 사용보다 안전하다.
public class StringGrade {
public static final String BASIC = "BASIC";
public static final String GOLD = "GOLD";
public static final String DIAMOND = "DIAMOND";
}
문자열 상수 사용 시 실수로 이름을 잘못 입력하면 컴파일 시점에 오류가 발생한다. 그러나 문자열 상수 또한 근본적인 해결 방법이 아니다. 위의 discount() 메서드를 보면 받을 수 있는 인자가 String으로 되어 있기 때문에 정의된 문자열 상수를 사용하지 않고 문자열을 직접 입력할 수 있다. discount()를 호출하는 개발자는 문자열 상수의 존재를 모를 수 있다.
타입 안전 열거형 패턴
이러한 문제들을 해결하기 위해 타입 안전 열거형 패턴 (Type-Safe Enum Pattern)을 도입한다. 나열한 항목이 아닌 것은 사용할 수 없도록 설계하여 위와 같은 문제가 생길 가능성을 원천 차단하는 것이다.
타입 안전 열거형 패턴을 직접 구현해 보자.
public class ClassGrade {
public static final ClassGrade BASIC = new ClassGrade();
public static final ClassGrade GOLD = new ClassGrade();
public static final ClassGrade DIAMOND = new ClassGrade();
//private 생성자 추가
private ClassGrade() {}
}
1. 회원 등급을 다루는 클래스를 만들고 회원 등급별로 상수를 선언한다.
2. 이때 각각의 상수마다 별도의 인스턴스를 생성하고 생성한 인스턴스를 대입한다.
3. 상수로 선언하기 위해 static, final을 사용한다. (static: 상수를 메서드 영역에 선언/ final: 인스턴스(참조값) 변경할 수 없게 함)
4. private 생성자를 사용해 외부에서 ClassGrade를 임의로 생성하지 못하도록 한다.
이렇게 타입 안전 열거형 패턴을 사용하게 되면 정해진 객체만을 사용할 수 있어 타입 안정성이 향상되고 데이터 일관성을 보장할 수 있다.
자바의 Enum 클래스
자바는 타입 안전 열거형 패턴을 쉽게 사용할 수 있게 열거형(Enum Type)을 제공한다.
public enum Grade {
BASIC, GOLD, DIAMOND
}
이 코드는 위의 타입 안전 열거형 패턴 코드와 같은 역할을 한다. 자바의 Enum은 하나의 클래스이며 java.lang.Enum을 상속받아 동작한다. 열거형 사용으로 코드의 간결성과 일관성을 보장할 수 있다. 또한 확장성과 유연성도 뛰어나다. 새로운 회원 등급을 추가하고 싶다면 enum에 새로운 상수를 추가하기만 하면 된다.
예를 들어, Enum을 통해 회원 등급을 정의하면 특정 등급에 대한 로직을 Enum 내부에 직접 포함시킬 수 있어 코드의 응집도를 높일 수 있다. 아래의 코드처럼 enum 클래스를 활용해 객체 지향 코드로 리팩터링 할 수 있다.
public enum Grade {
BASIC(10), GOLD(20), DIAMOND(30);
private final int discountPercent;
Grade(int discountPercent) {
this.discountPercent = discountPercent;
}
public int getDiscountPercent() {
return discountPercent;
}
public int discount(int price) {
return price * discountPercent / 100;
}
}
정리
자바의 Enum 타입은 타입 안정성을 보장한다. 문자열이나 상수를 사용하는 것보다 안전하고 효율적이며 코드의 확장성과 유지보수성을 향상할 수 있다. 따라서 여러 상수값을 관리하고 로직을 구현할 때 Enum을 활용하는 것이 좋다.
참고
'Tech Stack > Java' 카테고리의 다른 글
[Java] 컬렉션 프레임워크 List와 의존 관계 주입 (0) | 2024.08.16 |
---|---|
[Java] 래퍼 클래스 (Wrapper Class) (0) | 2024.08.13 |
[Java] String 클래스와 주요 메서드 (0) | 2024.08.13 |
[Java] 불변 객체 (Immutable Object) (0) | 2024.08.12 |
[Java] Object 클래스와 객체 지향 (0) | 2024.08.11 |