[Java Spring] 내부 구현을 통한 MessageSource, Validation 동작 원리 탐구

작성일 : 2023년 08월 10일
  • #Java
  • #Spring Boot

Spring Boot는 기본으로 MessageSource를 통한 메시지 기능과 Validation 기능을 제공한다. 그런데 MessageSource가 어떻게 동작하는지, 왜 RequestBody는 @Valid 어노테이션 만으로 유효성 검증이 되고 RequestParam은 조건부로 검증이 되며 Type level에 @Validated가 붙어야 하는지 궁금했다. 그래서 한번 내부 구현을 들여다보았다.

내부 구현 정리와 근거

  1. ApplicationContext는 MessageSource를 구현

    applicationContext는 MessageSource의 구현

    1. MessageSource는 Bean으로 등록된 것으로 설정

      ApplicationContext에서 MessageSource를 세팅하는 로직 일부

  2. MessageSource는 MessageSourceAutoConfiguration에서 bean으로 생성

    MessageSource가 bean으로 자동 설정되는 부분

  3. ValidationAutoConfiguration에서 defaultValidator bean 생성

    1. defaultValidator는 applicationContext bean을 등록

      Validator Bean이 생성되는 클래스

      • validator bean의 messageInterplator 적용부에 applicationContext가 들어감

      • MethodValidationPostProcessor는 ObjectProvider 통해 validator bean을 찾아 주입

        → Validator, MethodValidationPostProcessor는 동일한 validator를 사용

  4. WebMvcAutoConfiguration에서 mvcValidator를 등록

    WebMvcAutoConfiguration에서 mvcValidator 빈 생성

    • jakarta.validation.Validator 내부에 있는 validator를 가져오는 역할

    1. mvcValidator는 defaultValidator와 같음

  5. @RequestMapping은 requestMappingHandlerAdapter bean을 통해 처리

    RequestMapping 을 처리해주는 RequestMappingHandlerAdapter

    RequestMapping 을 처리해주는 RequestMappingHandlerAdapter

  6. Spring은 RequestMapping을 통해 받은 파라미터를 argumentResolver를 통해 처리

    Spring 동작 방식

    출처

    1. @RequestBody는 RequestResponseBodyMethodProcessor를 통해 처리

      1. RequestResponseBodyMethodProcessor는 @Valid가 붙은 validation을 처리

        @RequestBody의 데이터를 매핑 해주는 ArgumentResolver인 RequestResponseBodyMethodProcessor

        @RequestBody의 데이터를 매핑 해주는 ArgumentResolver인 RequestResponseBodyMethodProcessor

    2. Pageable 파라미터는 PageableHandlerMethodArgument에서 처리

      1. validation 되지 않음

        Pageable 객체를 만들어주는 PageableHandlerMethodArgumentResolver에는 validation이 이루어지지 않음

    3. 그 외 요청의 경우 각각 필요한 argumentResolver를 통해 처리

    4. argumentResolver에서 validation을 처리해주지 않는 경우 클래스 단에 @Validated 어노테이션을 붙여 MethodValidationPostProcessor를 통해 처리 되도록 해야함

      @Validated

      MethodValidationPostProcessor

      • 상기 내용과 같이 Method에 Validation Annotation처리가 되어있는 제약조건을 처리하기 위해 Type Level(클래스 단)에 붙어야함

        → PageableHandlerMethodArgumentResolver에서 validation을 해주지 않기 때문에 Validated를 통해 MethodValidationPostProcessor에서 동작하도록 설정

        → MethodValidationPostProcessor에 등록된 메서드는 MethodValidationInterceptor를 통해 validation 처리

        → requestMappingHandlerAdapter를 통해 처리되는 RequestMapping 메서드를 MethodValidationInterceptor가 가로채어 validation됨

      1. MethodValidationPostProcessor에 확인된 클래스 메서드는 실행 시 MethodValidationInterceptor를 통해 처리 중간에 가로채어 validation 됨

        MethodValidationInterceptor에서 validate 처리

        MethodValidationInterceptor

  7. RequestBody외 다른 파라미터는 클래스 단에 @Validated를 명시하여 MethodValidationInterceptor를 통해 가로채어 처리 해야함

    RequestMappingHandlerAdapter내 intercept 되는 부분