[Spring] 기본값 설정하기

·2024년 7월 26일
0

Spring

목록 보기
3/4
post-thumbnail

특정 필드에 Enum 타입의 기본값을 설정해 주어야 하는 일이 생겼다. 여러 가지 방법을 알아보고 고민하다가 다음과 같이 해결했다.

@ColumnDefault 어노테이션 사용

@ColumnDefault는 DDL을 생성할 때 자동으로 default 제약사항을 넣어주는 Hibernate의 어노테이션이다. DDL 생성 시에 자동으로 추가해 준다.

@Entity
public class NewEntity {
	... 
	
	// 예시로 NEW_TYPE이라는 필드를 만들었다.
	
	@Column(name = "NEW_TYPE", nullable = false)
	@ColumnDefault(NewType.DEFAULT_STRING)
	@Enumerated(EnumType.STRING)
	private NewType NewType;
	
	// getter .. 
}
public enum NewType {
	ATYPE,
	BTYPE,
	CTYPE;

	public static final NewType DEFAULT = ATYPE;
	// @ColumnDefault에서 Java 상수를 사용할 수 없어서 String으로 하드 코딩
	public static final String DEFAULT_STRING = "'ATYPE'";
}

해결할 수 있는 또 다른 방법이 있었다. JPA의 @Column(columnDefinition = "...") 어노테이션을 사용하는 것이다.

@ColumnDefault와 비교했을 때, columnDefinition은 더 넓은 범위의 컬럼 정의를 할 수 있지만, 데이터베이스 종속적인 SQL을 사용하게 될 수 있다는 단점이 있다.

@Entity
public class NewEntity {
    ...
    
    @Column(name = "NEW_TYPE", 
            nullable = false, 
            columnDefinition = "VARCHAR(255) DEFAULT 'ATYPE'")
    private NewType newType;
    
    // getter ..
}

오해하지 말아야 할 부분이 있는데, @ColumnDefault는 DDL만을 위한 설정이다. 애플리케이션 단에서 필드가 null인 상태로 save를 하려고 하면 오류가 발생한다는 뜻이다.

하지만 우리 서비스에서는 앱 버전이 낮은 사람들에게 오는 요청은 해당 Enum Type에 대한 필드가 비어있을 것이기 때문에 null로 들어올 것이라는 문제가 있었다.

이 문제를 해결하는 방법은 다음과 같다.
@DynamicInsert 붙이기

@DynamicInsert 를 사용한 예시는 다음과 같다.

@Entity
@DynamicInsert
public class NewEntity {
	... 
	
	// 예시로 NEW_TYPE이라는 필드를 만들었다.
	
	@Column(name = "NEW_TYPE", nullable = false)
	@ColumnDefault(NewType.DEFAULT_STRING)
	@Enumerated(EnumType.STRING)
	private NewType NewType;
	
	// getter .. 
}

이렇게 어노테이션을 추가하면, null 값인 필드를 제외한 INSERT 쿼리를 동적으로 생성한다. 때문에 약간의 오버헤드가 발생할 수 있다.

하지만 위의 방식은 다소 데이터베이스에 의존적이고 성능 오버헤드가 발생할 수 있어 다음과 같은 방식으로 null 값에 대해 처리해 줬다.

Entity 클래스 생성자에서 기본값 처리

RequestDto에 get 메서드를 직접 작성하여 기본값을 처리해 줄지, 서비스 레이어에서 처리할지, 엔티티 클래스에서 처리할지 고민하다가 엔티티 클래스에서 다음과 같이 생성자를 이용하여 처리해 줬다.

@Entity
public class NewEntity {
	... 
	
	private Long id;
	private String field1;
	private String field2;
	private NewType NewType;
	
	// 생성자
	protected NewEntity(String field1, String field2, NewType newType) {
		this.field1 = field1;
		this.field2 = field2;
		this.newType = (newType != null) ? newType : newType.DEFAULT;
	}
	
	public static NewEntity of( ...
	...
}

명시적으로 기본값을 설정하고, 기본값 로직을 한곳에서 처리할 수 있게 되었다.

하지만 데이터베이스 레벨의 기본값과 일치하지 않을 경우 혼란을 야기할 수 있다는 점을 염두에 두어야 한다.

참고

ColumnDefault (Hibernate Javadocs)

profile
개발블로그👩🏻‍💻

0개의 댓글