[Spring] 스프링 Enum Validator Reflection 으로 개선 및 구현하기
https://gengminy.tistory.com/47
앞서 작성한 스프링에서 Custom Enum Constraint Validator 구현하기
이 글에서 @Enum 이라는 커스텀 어노테이션을 만들었고
Request 필드에서 적용해보았다.
@Schema(defaultValue = "OPEN", description = "오픈 상태")
@Enum(target = EventStatus.class, message = "올바른 값을 입력해주세요.")
private EventStatus status;
하지만 이런식으로 작성하게 되면
매번 검증하고자 하는 Enum 클래스를 위처럼 명시해줘야 한다.
이게 보기 싫기 때문에 Reflection 을 통해 동적으로 Enum 클래스의 value 를 가져와 검증하려고 했다.
리플렉션(Reflection) : 실행 중인 프로그램의 클래스, 메서드, 필드 등의 정보를 동적으로 조사하고 사용하는 기능
클래스의 이름을 문자열로 받아와 그 클래스를 동적으로 로딩하거나, 인스턴스의 메소드나 필드를 호출하거나, 어떤 클래스가 어떤 인터페이스를 구현하고 있는지, 어떤 클래스가 어떤 클래스를 상속받았는지 등의 정보를 런타임에 조사할 수 있다.
📌 원하고자 하는 목표
@Schema(defaultValue = "OPEN", description = "오픈 상태")
@Enum(message = "올바른 값을 입력해주세요.")
private EventStatus status;
위 처럼 @Enum 사용 시 조사할 Enum 클래스를 생략하고 싶다.
📝 Enum
@Constraint(validatedBy = {EnumValidator.class})
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Enum {
String message() default "Invalid Enum Value.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
target 필드를 제외하여 재정의한다.
📝 EnumValidator
public class EnumValidator implements ConstraintValidator<Enum, java.lang.Enum> {
@Override
public boolean isValid(java.lang.Enum value, ConstraintValidatorContext context) {
if (value == null) {
return false; //null 값 허용 여부
}
Class<?> reflectionEnumClass = value.getDeclaringClass();
return Arrays.asList(reflectionEnumClass.getEnumConstants()).contains(value);
}
}
여러 가지 방법을 찾아보았는데 위의 방법이 가장 효과적인 것 같아서 채용했다
우선 해당 Enum 값이 null 일 경우를 검사한다.
여기서는 null 에 해당하는 값은 검증에 실패하도록 정책을 설정했다.
이후 이 Enum 값이 null 이 아님이 보장되었기 때문에
value.getDeclaringClass 를 통해 이 value 가 속한 Enum 클래스 정보를 가져온다.
이제 Enum Class 를 알아냈으니 이 Enum 에 속해있는 Constant 들을 가져와 비교하면 된다.
비교는 Collection 의 contains 메소드를 이용하여 축약시켰다.
이제 target 을 지정하지 않아도
동적으로 Enum Class 정보를 가져와 Validation 할 수 있게 되었다!
올바르게 검증해주는 모습
🌎 구현 과정 관련 게시글
📎 Custom Enum Validator 구현하기
https://gengminy.tistory.com/47
📎 Reflection 을 이용하여 Enum Validator 개선하기
https://gengminy.tistory.com/48
📎 Custom Enum Deserializer 구현하여 Enum 에 없는 값 null 로 파싱하기
https://gengminy.tistory.com/49