티스토리 뷰

@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);
    }
}

 

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

Total
Today
Yesterday
최근에 올라온 글
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30