ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [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);
        }
    }

     

    다음과 수정되었음을 알 수 있다.

Designed by Tistory.