JPA
JPA에서 @Enumerated 사용할 때 주의사항 정리
초코너무조코
2025. 5. 1. 11:48
728x90
JPA를 사용하면서 enum 타입을 매핑할 때 자주 사용되는 애노테이션이 @Enumerated입니다. 하지만 잘못 사용하면 치명적인 데이터 오류로 이어질 수 있으므로 주의가 필요합니다. 이 글에서는 @Enumerated의 사용법과 왜 EnumType.ORDINAL을 피해야 하는지 자세히 정리합니다.
@Enumerated란?
Java의 enum 타입을 JPA 엔티티 필드와 DB 컬럼 간에 어떻게 매핑할지 지정하는 애노테이션입니다.
@Enumerated(EnumType.STRING)
private Status status;
@Enumerated는 기본적으로 EnumType.ORDINAL 방식으로 동작합니다.
타입 | 설명 |
EnumType.ORDINAL | enum의 순서(index) 를 DB에 저장 (예: 0, 1, 2) |
EnumType.STRING | enum의 이름(name) 을 DB에 저장 (예: "READY", "DONE") |
EnumType.ORDINAL 사용하면 위험한 이유
public enum Status {
READY, // 0
IN_PROGRESS, // 1
DONE // 2
}
- 위 enum을 ORDINAL 방식으로 매핑하면 READY는 0, IN_PROGRESS는 1로 DB에 저장됩니다.
- 그런데, 나중에 enum이 이렇게 바뀐다면?
public enum Status {
WAITING, // 새로 추가됨
READY,
IN_PROGRESS,
DONE
}
- 이제 READY의 순서는 1번이 됩니다.
- 기존에 0으로 저장된 데이터는 JPA가 WAITING으로 잘못 매핑하게 됩니다.
- 결과: 데이터의 의미가 완전히 뒤바뀌는 심각한 문제 발생!
권장 방식: EnumType.STRING 사용
@Enumerated(EnumType.STRING)
private Status status;
- enum 이름 자체가 저장되므로 ("READY", "DONE" 등)
- 순서 변경이나 enum 추가에도 안전합니다.
- 실무에서는 무조건 STRING 사용을 권장합니다.
실습 예시
엔티티 예시
@Entity
public class Task {
@Id @GeneratedValue
private Long id;
@Enumerated(EnumType.STRING) // ⭐ 안전하게 enum 이름으로 저장
private Status status;
// getter, setter
}
enum 예시
public enum Status {
READY,
IN_PROGRESS,
DONE
}
저장 시
Task task = new Task();
task.setStatus(Status.READY);
entityManager.persist(task);
→ DB에 저장되는 값: "READY"
정리
항목 | ORDINAL | STRING |
저장값 | 숫자 인덱스 (0, 1, 2) | 이름 (예: "READY") |
enum 변경 시 안전성 | 낮음 (순서 영향 받음) | 높음 (이름 고정) |
실무 사용 권장 여부 | 비추천 | 추천 |
결론
JPA에서 enum을 매핑할 때는 반드시 @Enumerated(EnumType.STRING)을 사용하세요.
EnumType.ORDINAL은 처음에는 문제가 없어 보여도, 시간이 지나 enum 값이 바뀌면 데이터 전체를 망가뜨리는 지뢰가 될 수 있습니다.
안전하고 유지보수하기 쉬운 코드를 위해 항상 STRING 방식으로 저장하도록 습관화합시다!
728x90