ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • HandlerMethodArgumentResolver 동작 원리
    spring/core 2021. 3. 8. 23:06

    배경

    프로젝트에서 가장 기본 도메인인 회원의 CRUD를 구현하고 있었다. JPA를 이용해 큰 어려움 없이 CR기능은 구현했고 스무스하게 UD관련 기능을 구현했다. 별 고민없이 클라이언트에서 회원id와 함께 변경에 필요한 데이터를 api서버로 전달했다. api서버에서는 회원id와 나머지 변경을 원하는 데이터를 DTO로 받아 작업을 처리했다. 포스트맨을 이용해 간단히 테스트를 진행했는데 내 로직에 큰 결함이 있는 걸 알았다. id를 클라이언트에서 넘긴 후 그 id로 조회한 회원의 데이터를 수정할 수 있다면 어떤 회원이 악의적으로 다른 회원의 데이터를 수정할 수 있었다. 즉, 서버에서 인증한 회원이라면 다른 회원의 정보를 임의의 id를 통해 접근할 수 있는 것이었다.

     

    이 문제를 해결하기 위해 id에 의존한 회원 수정이 아닌 세션을 이용한 수정으로 변경했고, 기존 파라미터로 넘어왔던 id값은 적절히 세션으로 대체하기로 했다. 처음에는 스레드로컬에서 시큐리티의 유틸을 이용해 세션을 가져왔지만 java의 기본 기술만 이용하기로한 서비스로직에서 시큐리티에 종속된 코드가 나오니 보기 불편했다. 결국 방법을 찾던 중 애초에 컨트롤러에서 파라미터로 세션을 넘겨받을 방법을 생각해봤고(세션은 내가 만든 dto) HandlerMethodArgumentResolver를 알게 되었다.

     

     

    적용 방법

    애노테이션 세팅과 적용

    우선 커스텀 애노테이션을 만들고 세션을 받기 위한 컨트롤러의 파라미터에 애노테이션을 붙여 준다. 애노테이션은 단지 메서드 파라미터에 ArgumentResolver를 적용할 대상인지 판단할 목적으로 사용된다.

     

    리졸버 정의 및 빈등록

    그 후 HandlerMethodArgumentResolver를 구현한 클래스를 만든다. 스프링에 기본으로 정의된 많은 resolver가 있고 그 리스트에 추가될 클래스다. supportsParameter()를 이용해 resolver를 적용할 파라미터를 정하고 resolveArgument()를 이용해 구체적인 작업을 수행한다. @Component를 이용해 빈으로 등록하는 것도 잊지말자!

     

    list에 resolver 추가하기

    이후 방금 만든 Resolver를 리졸버리스트에 추가한다.

     

    동작원리

    스프링은 서블릿에 도착한 모든 요청에 대해 다음과 같은 전처리를 진행한다.

    1) 요청을 분석하여 핸들러매핑 결정

    2) 결정한 핸들러매핑으로 그에 맞는 어댑터 결정

    3) 어댑터를 이용해 요청을 핸들러로 처리

    4) 핸들러 매핑을 리플렉션하여 등록한 리졸버에 대응되는 파라미터 바인딩

     

    1~3은 나중에 자세히 분석하기로하고 여기서 핵심은 4번과정이다.

    코드를 보면 핸들러매핑의 메소드를 리플렉션하여 각 파라미터마다 리졸버리스트를 거친 뒤 적절한 리졸버와 매핑되면

    정해진 로직대로 파라미터를 넘기는 방식이다. 리졸버리스트를 봐보면

    36개 리졸버가 등록된 걸 확인할 수 있고 그중 25번째에 내가 등록한 리졸버를 확인할 수 있다.

     

     

    마치며

    - 토비의 스프링은 스프링 3.1버전을 반영하고 있고 3.1버전에서는 WebArgumentResolver를 사용한 모양이다. 찾아보니 3.2버전부터 WebArgumentResolver가 deprecated되었고 위에서 소개한 resolver를 이용한다.

    - 매번 느끼지만 요청 하나에 도대체 얼마나 많은 메소드를 실행하는지 모르겠다. 지금까지 까본것만 300개는 되는 것 같은데 알고리즘과 프로젝트를 같이 공부하면 뭐가 맞는지 헷갈린다.

    - 핸들러매핑부터 어댑터선정, 파라미터바인딩까지 추후 자세하게 파헤쳐보자^^

     

    'spring > core' 카테고리의 다른 글

    Spring Interceptor 사용 및 동작 정리  (0) 2021.05.14
    스프링 DI 방법  (0) 2021.05.06
    스프링 부트 자동설정 과정  (0) 2021.04.06
    DispatcherServlet에서 요청을 처리하는 과정  (0) 2021.04.05
    AOP 동작 원리  (0) 2021.03.06

    댓글

Designed by Tistory.