Filter, Interceptor는 뭐지??

kimseungki·2023년 4월 17일
1

개요

IT-Hermes 프로젝트 개발 과정 중, 이슈는 다음과 같았습니다. 전 Spring Security를 썼는데, 이유는 인증과 인가를 편하게 하기위한 최적에 프레임워크라 판단해서 썼습니다. 근데 하나의 문제가 있었습니다.
Hermes 프로젝트에서 예외처리의 경우

이런 식으로 별도의 핸들러를 통해 관리를 했었습니다.
그래서 Security를 쓸 경우에도, 예외가 토큰만료, 토큰이 잘못된거 등의 이슈가 있기 때문에 여기서 편하게(?) 관리를 하고 싶었는데, 이상하게 예외처리가 원하는대로 안나는 것이 이유였습니다.
저는 여기서 깨달았습니다... Filter과 Interceptor를요..

Filter?

Filter은 DispatcherServlet가 실행되기 전에 부가 기능을 수행하는 기능을 제공합니다.

  • DispatcherServlet는 서블릿 컨테이너 안에 있으며, 요청을 처리할 Handler를 핸들러 매핑을 통해 요청합니다. 이후 실행을 하는데, 보통 Controller 이나 View Resolver를 실행하죠. 즉 DispatcherServlet 이후에 로직은 스프링의 기능을 쓸 수 있는거죠.
    즉 SpringMVC 환경과 Filter은 전혀 다른 곳에서 작동을 하는거죠.
    Spring Security는 Filter에서 인증 혹은 인가의 로직을 수행합니다. 따라서.. 제가 하려고 한 행위는..

    여기에서 ControllerAdvice를 한 AOP 영역에다 예외처리 해놓고, Filter에서 예외를 호출하길 기대한 것입니다...
    지금 생각해보면.. 스프링이 어떻게 작동하는지 몰랐던거같네요...

Inteceptor?

DispatcherServlet가 핸들러 매핑 요청 시 Controller 정보 뿐만 아니라 실행 체인을 받는데 이 과정에서 체인으로 인터셉터가 등록이 될 때 실행이 되는 것을 말합니다. 핸들러 매핑이 Controller를 찾을 때는 @RequestMapping의 url path 등을 참고하는 거죠
그래서 Controller를 참고하고 실행하려고 할 때, 인터셉터가 먼저 호출이 되고, 이후 Controller의 로직이 호출되게 됩니다. 만약? AOP로 부가로직이 수행될 경우? 프록시 객체가 가로채서 실행이 되는거죠

그림에 대한 부가적인 설명

  1. 클라이언트가 요청을 하면 전 Nginx에서 로드밸런싱이나 캐시 비활성화 같은 기능을 수행하도록 했습니다.
  2. 그 이후, 서버가 호출이 되고, WAS로 이동하여 Filter에서 인증관련 부가기능을 수행하도록 했습니다.
    (Servlet Container?가 필요한거 아닌가? 라는 생각을 하시는 분들이 있다면..
    SpringBoot 환경에서는 Servlet Container(Tomcat)가 내장되어있고, 모든 요청을
    DispatcherServlet에 보냅니다.
    따라서 여러 Url을 매핑한 여러 Servlet 클래스를 DispatcherServlet 하나에서 처리하도록 했기 때문에, 안썻다고 생각하면 좋을 듯 합니다..)
  3. Dispatcher Servlet에서 핸들러 매핑을 통해 Controller을 찾습니다. 만약 실행 체인에 인터셉터가 있을경우 실행하고요
    (요청을 할 수 있는 이유는? Spring Contatiner에서 기능에 필요한 객체를 가져오기 때문이죠)
  4. 그리고 핸들러 어뎁터에 의해 핸들러에 맞는 어뎁터를 호출하게 됩니다.
    (보통 @RequestMapping 같은거를 호출한다면 애노테이션 기반인
    AnnotationMethodHandlerAdapter가 호출되죠)
  5. 컨트롤러가 호출되기 전 AOP를 통해 처리하는게 있을 경우, 프록시 객체를 통해 처리됩니다.

Spring Security

이 과정에서 느낀 점은, Spring Security가 Filter에 코드를 넣는것은 처리속도 상에 이점이 있기 때문인걸 알았습니다. 결국 Filter에서 처리하면 굳이 Dispatcher에서 처리할 필요도 없기 때문이죠..

적용


다행이 Security에서 Handler을 제공해주었고, 원하는 예외를 여기에 적용시킬 수 있었습니다.
그 과정에서 HttpServletRequest가 왜 있는지 이해를 못했는데.. 생각해보니까.. Spring이 아닌 서블릿에서 작동되는게 큰 원인이었죠.
위의 코드는 인증은 되었지만, 권한이 없는 사용자가 접근할 수 없는 요청을 할 때 예외처리를 한 부분입니다.
(생각해보니까.. 예외 이름을 다르게 주는게 나을거같네요.. ㅎㅎ)

위의 코드는 인증이 되지 않은 사용자에게 예외를 날릴 때 쓰는 겁니다. 저는 만료와 인증 토큰이 잘못되었을 때 여기 있는 예외를 통해 처리하려고 했습니다.

결과


원하는대로 예외처리를 할 수 있었습니다.

주의할 점

이 과정을 바탕으로 프레임워크를 쓸 때는, 항상 어떻게 작동되는지를 명확히 아는 것이 중요하다는 것을 알게 되었습니다. 스프링의 작동원리를 다시 한 번 공부하는 계기가 되었던거같습니다.

profile
seung 기술블로그

0개의 댓글