Deep Dive /Java Web /12-2

12-2. WebDataBinder → SmartValidator: validate() (@Valid 검증)

DTO 생성이 끝나면, Spring은 WebDataBinderSmartValidator를 사용해 @Valid 검증을 수행합니다.


이번 단계의 역할 — 역직렬화된 객체가 컨트롤러에 들어가기 전 유효한지 검사한다

역직렬화된 객체가 컨트롤러에 들어가기 전에 유효한지 검사하는 단계입니다.


호출 흐름 요약 — createBinder() → validateIfApplicable() → binder.validate()

  1. RequestResponseBodyMethodProcessorWebDataBinder를 생성합니다.
  2. validateIfApplicable(...)가 검증 어노테이션을 확인합니다.
  3. binder.validate(...)SmartValidator로 위임됩니다.
  4. BindingResult에 오류가 쌓입니다.
  5. 오류가 있으면 MethodArgumentNotValidException으로 전환됩니다.

호출 흐름 다이어그램 — WebDataBinder가 SmartValidator로 위임하고 결과는 BindingResult에 쌓인다

sequenceDiagram participant RR as RequestResponseBodyMethodProcessor participant BF as WebDataBinderFactory participant Binder as WebDataBinder participant Validator as SmartValidator participant BR as BindingResult RR->>BF: createBinder(...) BF-->>RR: WebDataBinder RR->>Binder: validate(...) Binder->>Validator: validate(target, errors) Validator-->>BR: violation info

핵심 코드 — validateIfApplicable() 실패는 MethodArgumentNotValidException으로 던져진다

// RequestResponseBodyMethodProcessor.java
WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name, type);
if (arg != null) {
    validateIfApplicable(binder, parameter);
    if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
        throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
    }
}

코드 해설 — JSON 파싱이 성공한 뒤에만 검증이 돌고 결과는 BindingResult에 모인다

역직렬화와 검증이 분리되어 있기 때문에, JSON 파싱이 성공한 뒤에만 검증이 진행됩니다. 또한 검증 결과는 BindingResult라는 표준 결과 객체에 쌓입니다.


설계 의도 — 바인딩 결과와 검증 결과를 BindingResult 한 곳에 모은다

바인딩 결과와 검증 결과를 같은 컨테이너(BindingResult)에 모아, 컨트롤러 진입 전 오류 여부를 일관되게 판단하기 위한 구조입니다.


다음 단계 연결 — 12-3 검증 오류가 예외 처리 체인으로 넘어가는 과정으로 이어진다

다음 문서 12-3에서는 이 검증 오류가 DispatcherServlet의 예외 처리 체인으로 어떻게 넘어가는지 봅니다.

← 이전: 12-1. AbstractJackson2HttpMessageConverter → ObjectMapper | 다음: 12-3. DispatcherServlet → ExceptionHandler