기존의 Spring Boot 2.7.x 프로젝트를 Spring Boot 3 으로 올리면서 발생하는 이슈입니다.
기본 Spring Boot 2.7.x 에서는 Hibernate 5.6.x가 기본 설정이었으나, Spring Boot 3 부터는 Hibernate6 버전을 기본으로 사용합니다.
Spring Boot 3 와 Hibernate 6을 사용하면서 Enum 타입을 처리할 때 예상치 못한 문제가 발생할 수 있어요. 이번 포스팅에서는 그 원인과 해결 방법을 알아보겠습니다.
문제 상황
@Enumerated(EnumType.STRING) 만으로 테이블 컬럼 타입이 VARCHAR 형태로 생성되지 않음.
JPA를 사용하면서 Enum Type을 사용하면 컬럼이 ordinal 값으로 등록이 되어 Enum 에는 @Enumerated(EnumType.STRING) 옵션을 적용해 컬럼 타입을 VARCHAR 형태로 적용해왔습니다.
@Enumerated(EnumType.STRING)만 명시하면 ddl-auto 옵션을 통해 테이블 생성 시 varchar 타입으로 생성을 도와주었습니다.
@Entity
public class SampleEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Enumerated(EnumType.STRING)
private SampleEnum status;
}
하지만 Spring Boot 3과 Hibernate 6 환경에서 @Enumerated(EnumType.STRING)을 사용하여 Enum을 매핑했을 때, MariaDB 기준으로 enum 타입으로 컬럼이 생성됩니다.
create table sample_entity (
id bigint generated by default as identity,
status enum ('status1', 'status2'),
primary key (id)
);
이는 Hibernate 6에서 추가된 기능으로, 데이터베이스의 무결성을 보장하려는 의도로 보이지만, 운영 환경에서 Enum 값이 변경될 경우 문제가 발생할 수 있습니다.
해결 방법
1. @JdbcTypeCode 어노테이션 사용
검색을 통해 원래 원하는 의도대로 varchar type 컬럼 생성을 위해서는
@JdbcTypeCode(SqlTypes.VARCHAR)을 명시하면 된다는 가이드대로 추가하였습니다.
@Entity
public class SampleEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@JdbcTypeCode(SqlTypes.VARCHAR)
@Enumerated(EnumType.STRING)
private SampleEnum status;
}
이렇게 설정하면 원하던 varchar type의 컬럼은 맞지만 Hibernate가 DDL을 생성할 때 다음과 같이 CHECK 제약 조건을 포함합니다.
create table sample_entity (
id bigint generated by default as identity,
status varchar(255) check (status in ('STATUS1', 'STATUS2')),
primary key (id)
)
역시 위와 마찬가지로 운영 환경에서 Enum 값이 변경될 경우 문제가 발생할 수 있습니다.
2. @Column, column definition 선언
CHECK 제약 조건을 사용하지 않으려면 columnDefinition 을 통해 원하는 처리를 할 수 있었습니다.
@Entity
public class SampleEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(columnDefinition = "varchar(50)")
@Enumerated(EnumType.STRING)
private SampleEnum status;
}
결론
Spring Boot 3과 Hibernate 6을 사용할 때, @Enumerated(EnumType.STRING)만 사용할 경우 CHECK 제약 조건이 자동으로 추가되는 문제가 발생할 수 있습니다. 이를 방지하려면 @Column(columnDefinition = "varchar") 어노테이션을 사용하면 원하는 컬럼 타입으로 정의할 수 있습니다.
이 방법을 적용하면 Enum 값이 변경될 경우에도 데이터베이스 스키마를 변경하지 않고 운영할 수 있습니다.
하지만, 일반적으로 운영환경에서는 ddl-auto를 이용해서 테이블을 생성하기보다는 DDL을 직접 작성하여 관리하거나, Flyway와 같은 라이브러리로 데이터베이스 마이그레이션을 하거나, 또는 인프라나 데이터를 조직에서 DB를 관리하기도 합니다.
다만 이전 버전과 변경된 부분을 모르고 놓치고 지나치면 장애로 이어질 수 있기에 인지하고 있어야 할 부분인 것 같습니다.
Hibernate 6의 변화에 맞춰 적절한 설정을 적용하여 안정적인 개발 환경을 유지하시길 바랍니다.
'java' 카테고리의 다른 글
Sitemesh PageFilter VS SiteMeshFilter (0) | 2013.11.28 |
---|---|
java main 메소드에 public static을 쓰는 이유 (0) | 2013.10.17 |
JAR 파일 만들기 (0) | 2012.04.03 |