DTO는 데이터 전송을 위해 설계된 객체로, 데이터를 단순하고 명확하게 전달하는 것을 목적으로 합니다. 불필요한 로직이나 비즈니스 규칙은 포함하지 않는 것이 이상적입니다.
DTO 필드로 Enum 타입을 두는 것은 도메인과 DTO의 결합도를 높입니다.
예를 들면, Enum 값을 추가하거나 변경하면 DTO 쪽도 수정을 해줘야 하는 상황이 발생한다.
Enum 타입을 JSON으로 직렬화시켜야 하기에 클라이언트와의 데이터 통신이 원활하지 않게 됩니다.
String 타입을 사용하고 Custom Validation을 만들어 검증을 해주자.
Custom Validation
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ValidEnumValidator.class)
public @interface ValidEnum {
String message() default "값이 유효하지 않습니다.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
// 검증할 Enum 클래스를 지정하는 속성
Class<? extends Enum<?>> enumClass();
}
ValidEnumValidator 구현체
public class ValidEnumValidator implements ConstraintValidator<ValidEnum, String> {
private Set<String> enumValues;
@Override
public void initialize(ValidEnum annotation) {
// Enum 클래스에서 모든 값의 이름을 가져와 Set으로 저장
enumValues = Arrays.stream(annotation.enumClass().getEnumConstants())
.map(Enum::name)
.collect(Collectors.toSet());
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// 필드가 null이거나 비어 있을 경우 유효성을 true로 반환
if (value == null || value.isEmpty()) {
return true;
}
// 필드의 값이 Enum 값들에 포함되어 있는지 확인
return enumValues.contains(value);
}
}
DTO
@ValidEnum(enumClass = OrderStatus.class, message = "주문 상태가 유효하지 않습니다. 다시 시도해 주세요.")
private final String orderStatus;
https://easy-stack.tistory.com/entry/Spring-DTO-설계-시-Enum-타입을-피해야-하는-이유