spring

@RequestBody @Valid Object obj, BindingResult br 타입에러가 br에 담기지 않는 이유

devJK93 2024. 11. 30.

 

@RequestBody와 @Valid의 동작 방식

동작 원리 설명

@RequestBody @Valid ItemSaveForm form, BindingResult br의 경우:

  • @RequestBody는 클라이언트 요청의 HTTP 본문을 Java 객체로 변환합니다. 이 과정은 HttpMessageConverter가 담당합니다.
  • 변환 중에 JSON → Java 객체로 매핑 시 타입 에러가 발생하면, Spring은 컨트롤러 메서드에 접근하지 않고 예외(HttpMessageNotReadableException 등)를 던집니다.
  • 따라서, BindingResult에 에러가 바인딩되지 않고, 컨트롤러 메서드 실행 전에 예외가 발생하여 정상 동작하지 않습니다.

@Valid ItemSaveForm form, BindingResult br의 경우:

  • @Valid는 Spring Validator를 사용하여 객체에 대한 유효성 검사를 수행합니다.
  • 여기서 중요한 점은 타입 변환이 성공한 후에 유효성 검증이 실행됩니다.
  • 만약 유효성 검증 에러가 발생하면, BindingResult에 에러가 추가되고 컨트롤러 메서드가 정상적으로 실행됩니다.

차이점 요약

구분 @RequestBody @Valid @Valid
데이터 소스 JSON / XML (Request Body) 요청 파라미터
바인딩 실패 시 동작 예외 발생 (컨트롤러 도달 X) BindingResult에 에러 저장
검증 실패 시 동작 검증 후 컨트롤러 도달, BindingResult 사용 가능 동일

해결 방법

만약 @RequestBody를 사용하는 경우에도 타입 변환 에러를 컨트롤하고 싶다면, 예외를 처리하는 방식으로 해결할 수 있습니다:

1. @ControllerAdvice를 사용한 글로벌 예외 처리

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseEntity<String> handleHttpMessageNotReadable(HttpMessageNotReadableException ex) {
        return ResponseEntity.badRequest().body("Invalid request body: " + ex.getMessage());
    }
}

2. 커스텀 메시지 반환

컨트롤러에서 @RequestBody를 제거하거나, 에러 메시지를 사용자 정의로 처리.

정리

  • @RequestBody는 JSON 파싱 단계에서 에러가 발생하면 BindingResult로 에러를 전달하지 못합니다.
  • @Valid는 파싱이 끝난 후에 실행되므로, 타입 변환 문제 없이 유효성 검증 에러를 BindingResult로 처리할 수 있습니다.

이러한 차이를 이해하여 상황에 맞게 처리 방식을 선택하면 됩니다.

댓글