Request Body에서 Enum을 바로 바인딩할 때 잘못된 Enum Constant의 이름을 입력할 경우 위와 같은 에러메시지를 보게 된다.
이 때 던져지는 예외는 HttpMessageNotReadableException인데 내가 원하는 메시지를 파싱하기가 쉽지 않고, 이미 정의해둔 MethodArgumentNotValidException 응답 스펙을 사용하고 싶었다.
Bean Validation은 이미 바인딩된 객체에 대해서 유효성 검증을 수행하는데, 위와 같은 예외는 역직렬화 과정에서 입력받은 String을 name으로 갖는 enum constant를 찾지 못하여 Bean Validation이 수행되기 전 단계에서 일어난다.
처음 든 생각은 역직렬화에 사용되는 JsonCreator 메소드를 정의하여 메소드 내에서 유효성 검증을 수행하는 것이다.
생성자 파라미터인 MethodParameter 클래스와 BindingResult 클래스에 대해 이해가 부족하기도 했고 예외를 직접 던지려다 보니 코드가 매우 지저분해진다는 생각이 들었다.
Custom Validator가 수행되지 않고 바로 메소드가 실행된다. 역시 Bean Validation 스펙과 @Validated 어노테이션에 대한 나의 이해가 부족한 것 같았다.
다음과 같은 두가지 아쉬움이 있었다.
1-1. 입력받은 문자열부터 다시 enum constant를 얻는 추가 코드가 필요하다.
1-2. 입력받은 문자열을 검증할 때와 문자열로부터 enum constant를 얻을 때 O(N)의 작업이 두번 수행된다.
-> Enum Class 내부에 static 멤버로 name과 Enum Constant를 key, value로 갖는 HashMap을 정의하고 JsonCreator와 valueOf 메소드를 오버라이딩하는 식으로 개선할 수 있을 것 같다.
2-1. 만료 옵션을 선택하지 않았을 때 expirationPeriod을 null로 받으려 했었는데 이 경우에는 불가능하다.
2-2. @NotNull 어노테이션 이름만 봐서는 어떤 유효성 검증을 수행하는지 정확히 파악하기가 불가능하다.
두번째 방법을 선택했다.
두가지 방법 다 완벽히 만족스럽지가 않아서 MethodArgumentException과 Bean Validation 그리고 Spring의 데이터 바인딩에 더 공부해보고 코드를 개선