-
[Spring] @Valid 검증 실패 시에 default message 출력하기legacy/Spring 2024. 3. 26. 23:11
@Valid
Controller로 넘어오는 데이터를 검증하는 데 사용할 수 있다. 예를 들어, API를 호출할 때 user의 id를 반드시 전달해야 할 경우 @NotNull(message = "사용자의 id는 필수 정보입니다.")와 같이 검증 조건을 추가할 수 있다.
@Getter public class FindSectionCountRequestDto { @NotNull(message = "회고 보드 ID는 필수 입력 값입니다.") private Long retrospectiveId; @NotNull(message = "템플릿 섹션 ID는 필수 입력 값입니다.") private Long templateSectionId; }
Controller에서 API를 호출할 때 위에서 정의한 dto를 받는다. 위에서 사용한 검증 조건을 잘 준수했는지 확인하기 위해서 @Valid 애너테이션을 사용해야 한다.
@GetMapping("/counts") public CommonApiResponse<FindSectionCountResponseDto> getSectionCounts(@RequestBody @Valid FindSectionCountRequestDto request) { FindSectionCountResponseDto response = sectionService.getSectionCounts(request); return CommonApiResponse.successResponse(HttpStatus.OK, response); }
검증 실패 시 던지는 예외 클래스와 예외 메시지
다음 데이터를 담은 dto를 controller에 전달한다.
{ "retrospectiveId":1 }
위 데이터의 문제는 templateSectionId에 대한 데이터가 존재하지 않는 것이다. 이는 @NotNull 조건을 준수하지 않은 것으로 되어 @Valid에 의해 검증에 실패하게 된다.
검증에 실패한 경우 MethodArgumentNotValidException 예외 클래스가 발생한다. 나는 @ExceptionHanlder를 사용하여 전역에서 발생하는 예외를 한 곳에서 처리하도록 다음과 같이 코드를 작성했다.
@RestControllerAdvice @Slf4j public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<ErrorResponse> validMissingParameterException(MethodArgumentNotValidException ex) { log.error("유효성 검사 실패", ex); ErrorResponse response = new ErrorResponse(ErrorCode.MISSING_REQUEST_PARAMETER, ex.getMessage()); return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); } }
위에서 예외를 처리하고 클라이언트에 다음 메시지를 전달한다.
여기서 문제점은 예외 메시지가 너무 길다는 것이다. 나는 @NotNull에 작성한 "템플릿 섹션 ID는 필수 입력 값입니다."만 필요할 뿐이다.
검증 애너테이션에 작성한 default message만 가져오기 위해서 다음과 같이 작성한다. getDefaultMessage()를 통해 기본으로 등록된 메시지를 가져올 수 있다.
@RestControllerAdvice @Slf4j public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<ErrorResponse> validMissingParameterException(MethodArgumentNotValidException ex) { log.error("유효성 검사 실패", ex); String errorMessage = ex.getBindingResult().getFieldError().getDefaultMessage(); ErrorResponse response = new ErrorResponse(ErrorCode.MISSING_REQUEST_PARAMETER, errorMessage); return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); } }
다음과 수정되었음을 알 수 있다.