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