- [Effective Java] 6장 열거 타입과 애너테이션
- [Java] Enum to Json / Enum to Object
- https://woowabros.github.io/tools/2017/07/10/java-enum-uses.html
enum VS hashmap
- https://medium.com/@nikitashahu/enum-vs-hashmaps-for-storing-constants-204ef4a1a8d7
- code navigator의 도움을 받을 수도 있고,
- 없는 enum value를 잘못 참조했을 경우 compile time에 잡아낼 수도 있다는 장점도 있음.
code 1 : 현금, 2 : 카드 라는 정보를 관리하는 방법
- DB에 code table을 만들어서 관리
- 어드민 메뉴로 새로운 코드를 추가하는 것이 용이함. (삭제/수정은 constraint를 잘 써야 무결성 유지가 가능함)
- 단점은 코드에서 code, name을 String으로 받아와 관리해야 한다. 로직은 또 따로 두어야 한다.
- 매번 DB에서 읽어오는게 부담일 수 있다. 고작 이거 구분값 읽어오자고 DB를? 이라는 생각이 들 수도.
- DB에 있는 코드 표를 enum으로 아예 옮겨버리는 방법 (배민 enum 활용기)
- 코드 상에서 code와 name을 enum 타입으로 묶어서 들고다닐 수 있다. + 로직까지.
- 매번 DB에서 읽어오는건 부담스러우나, enum으로 변환하는건 아주 마음이 가볍다.
- 기타
- DBMS function을 이용해 코드 변환 (매번 조인보다 낫다)
- redis에 코드 테이블 올려두고 사용하는 방법
- 객체 내부에 Holder를 두어 같은 내용으로 두 번 resolve 하지 않도록 캐시처럼 사용하는 방법
- 하지만 이건 DB가 업데이트 되면 캐시도 업데이트 해주어야 한다는 문제점이 있어 좋지 않다.
enum을 쓰든, DB code table 을 참조하든 둘 중 하나만 하는 것이 좋긴 한데...
- 관리 포인트가 늘어나니까. 둘 중 하나만 쓰는게 웬만하면 좋긴 하지. 수정 사항이 발생했을 때 DB, enum 둘 다 반영해야 하므로.
- 이미 DB "결제 코드" table이 존재하고, 사용하는 중이라면? 게다가 enum으로 옮기기가 좀 곤란한 상황이라면?
- enum을 만드는게 이득이 크다고 판단되면 DB에 있어도 enum도 만들 수도 있다.
- 빈번히 참조되는데 변경이 자주 일어나지 않는 경우..? 이런 경우 굳이 DB 테이블을 enum으로 옮길 필요는 없는 듯.
enum도 결국 소스코드이기 때문에, 변경이 발생한다면 다시 컴파일해야 한다.
- 컴파일 시간이 굉장히 오래 걸린다면 단점 이겠지만 보통의 경우는 글쎄.
- 상수 값이 자주 변경된다면, `` .yml, .properties``같이 외부로 빼면 컴파일 없이 jar 패키징만 해도 적용 가능하다.
- spring에서 .properties에 있는 값을 enum에 세팅하려면?
enum은 extends는 불가하지만, implements는 가능하다.
- 공통 interface를 만들 때는, getter의 선언부가 인터페이스에 들어가줘야 해당 인터페이스 타입으로 접근했을 때 .getCode() 같은 메서드를 호출할 수 있다. (클래스 구현부에서는 @Getter를 써도 된다.)
예제
```java
// Getter가 정의되어 있어야 .getCode()같은 것으로 내부 값을 가져올 수 있다. interface를 쓰는 경우는 추가적으로 인터페이스 쪽에 getter를 선언해야 할 수 있다.
@Getter
@RequiredArgsConstructor
public enum PaymentCode {
CASH(1, "현금", "cash"), // 여기서 세번째 인자는 별로 필요없지만 이렇게도 가능하다는 것을 보여주기 위해.
CARD(2, "카드", "card");
private final int code;
private final String koName;
private final String enName;
public static PaymentCode fromKoName(String text){
for (PaymentCode code :values()){
if (code.getKoName().equals(text)) {
return code;
}
}
throw new IllegalArgumentException();
}
}
```
```java
/**
* 위 코드와는 관련 없지만 함수형으로 쓰면 이런 식이 된다.
*/
public static PaycoResponseCode from(int _code) {
return Stream.of(values())
.filter(responseCode -> responseCode.getCode() == _code)
.findAny()
.orElseThrow(NoSuchElementException::new);
}
```
- 위 방식은 매번 호출할 때 마다 for나 stream을 돌게 되는데, Map으로 key-value를 미리 저장해 두고 거기서 꺼내는 식으로 해도 좋다.
- enum.values()가 매번 호출되는 것을 막기 위해 enum factory를 사용하거나, static 변수에 이를 담아두는 경우가 있는데, 굳이 그럴 필요 까지는 없다.
```java
/* 기본 제공 */
log.info("{}", Payment.PaymentCode.valueOf("CARD")); // CARD 아래와 같다. 이름 문자열 받아서 enum찾을 때 말고는 쓸일 없는 듯.
log.info("{}", Payment.PaymentCode.CARD); // CARD 위와 같다.
log.info("{}", Payment.PaymentCode.CARD.name()); // CARD
// Payment.PaymentCode.values() 이 것도 있다.
/* @Getter */
log.info("{}", Payment.PaymentCode.CARD.getEnName()); // card
log.info("{}", Payment.PaymentCode.CARD.getKoName()); // 카드
log.info("{}", Payment.PaymentCode.CARD.getCode()); // 2
/* 직접 정의. */
log.info("{}", Payment.PaymentCode.fromKoName("현금")); // CASH
```
'Languages & Frameworks > Java' 카테고리의 다른 글
[Effective Java] 3장 모든 객체의 공통 메서드 (0) | 2019.12.04 |
---|---|
[Effective Java] 2장 객체 생성과 파괴 (0) | 2019.12.02 |
[java] 날짜 시간 처리 관련 (0) | 2019.07.10 |
[Java] Enum (0) | 2019.06.06 |
[Java] Stream API 노트 (0) | 2017.03.09 |
[Java] lambda 기본 개념 (0) | 2017.02.07 |