Spring/스프링 기본

Filters vs HandlerInterceptors - 개념

공대키메라 2022. 2. 28. 10:53

오늘은 filter와 interceptor에 대해서 정리하려고 한다. 

 

둘 다 기능은 비슷한데 어떤 차이가 있는지 잘 모르겠다!

 

그래서 이번 기회에 정리하려고 한다. 

1. Filter

J2EE의 표준 스펙 기능.(Springframework의 기능이 아님). filter는 인터페이스로 선언되어있다. 

 

Oracle에서는 다음과 같이 설명한다. 

A filter is an object that performs filtering tasks on either the request to a resource (a servlet or static content), or on the response from a resource, or both.
Filters perform filtering in the doFilter method. Every Filter has access to a FilterConfig object from which it can obtain its initialization parameters, and a reference to the ServletContext which it can use, for example, to load resources needed for filtering tasks.

출처 : https://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html

 

https://docs.oracle.com/cd/B14099_19/web.1012/b14017/filters.htm


이 친구가 어디있는지 찾아보았다.

 

 

수많은 Filter가 있지만 당황하지 않고 javax.servlet의 Filter를 클릭하면 된다. 

 

기본적으로 init, doFilter, destroy로 구성이 되어 있는데 상속받아서 doFilter만 구현해도 된다. 

(init, destroy는 deafult로 선언되어 있음)

 

한 번 설명을 읽어보도록 할까?

init method

Called by the web container to indicate to a filter that it is being placed into service. The servlet container calls the init method exactly once after instantiating the filter.

이하 생략...

 

필터 실행시 가장 처음 실행되는 부분. 

doFilter Method

The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain. The FilterChain passed in to this method allows the Filter to pass on the request and response to the next entity in the chain.

 

요청, 응답이 오고가면서 설정한 기능을 실행하는 부분. 

 

흥미로운 부분은 Filterchain 이라는 파라미터를 전달한다는 것이다. 

 

FilterChain을 한번 찾아보면 다음과 같이 설명해주고 있다. 

A FilterChain is an object provided by the servlet container to the developer giving a view into the invocation chain of a filtered request for a resource. Filters use the FilterChain to invoke the next filter in the chain, or if the calling filter is the last filter in the chain, to invoke the resource at the end of the chain 

이하 생략...

 

Filter은 FilterChain을 다음 filter를 invoke하려고 사용한다는데 결국 여러개의 filter를 이어주기 위해 사용한다는 것이다. 이 모든 filter가 끝이 나면 그다음에는 resource를 invoke하는 것이다. invoke는 실행한다고 일으면 적당할 것 같다.

destroy method

Called by the web container to indicate to a filter that it is being taken out of service. This method is only called once all threads within the filter's doFilter method have exited or after a timeout period has passed. After the web container calls this method, it will not call the doFilter method again on this instance of the filter.

이하 생략...

내가 선언한 filter가 끝날 때 기능을 실행하는 부분. 오직 filter가 끝날때 딱 한 번 실행됨. 

 

주석이 참 친절하기에 그냥 intelliJ에서 파일을 직접 검색해서 보면 끝이다. 

 

daeldung에서는 다음과 같이 소개하고 있다. 

2. Filters

Filters are part of the webserver and not the Spring framework. For incoming requests, we can use filters to manipulate and even block requests from reaching any servlet. Vice versa, we can also block responses from reaching the client.

=> 필터는 스프링 프레임워크가 아닌 webserver의 부분이다. 오는 요청에 도달하는 모든 servlet에 요청을 막거나 조작하기 위해 사용한다. 반대도 마찬가지로, 클라이언트에 도달하는 응답도 막을 수 있다.

Spring Security is a great example of using filters for authentication and authorization. To configure Spring Security, we simply need to add a single filter, the DelegatingFilterProxy. Spring Security can then intercept all incoming and outgoing traffic. This is why Spring Security can be used outside of Spring MVC.

 

읽어보면 spring security에서 인증과 허가에 Filter를 많이 사용한다고 한다. 

 

2. HandlerInterceptor

HandlerInterceptor도 기능은 앞에서 본 filter와는 기능이 비슷하다. 

 

하지만 그림을 보면 차이가 좀 명확한데 어느 순간에 이것이 작동하는지 다르다.

https://www.baeldung.com/spring-mvc-handlerinterceptor-vs-filter

뭔가 부족한거 같아서 다른 것도 찾아와서 첨부한다.

 

https://mangkyu.tistory.com/173

 

이것에 대해 설명하는 주석이 많이 길기에

 

중간에 하나만 가져왔다.

 

HandlerInterceptor is basically similar to a Servlet Filter, but in contrast to the latter it just allows custom pre-processing with the option of prohibiting the execution of the handler itself, and custom post-processing. Filters are more powerful, for example they allow for exchanging the request and response objects that are handed down the chain. Note that a filter gets configured in web.xml, a HandlerInterceptor in the application context.

 

HandlerInterceptor는 기본적으로 Servlet Filter와 동일하지만 Filter의 경우에는 핸들러 그 자체의 실행을 pre-processing와 post-processing과정에서만 금지하는 기능을 제공한다.

 

여기서 pre-processing이란 어떤 일을 수행하기 전에 일어나는 작업, post-processing은 어떤 일을 수행한 후 작업을 말한다.

 

HandlerInterceptor에 정의된 메소드는 3개가 있다. 

 

  • preHandle() – Executed before the target handler is called
  • postHandle() – Executed after the target handler but before the DispatcherServlet renders the view
  • afterCompletion() – Callback after completion of request processing and view rendering

3. Filter vs Interceptor

두개의 차이점을 이제 비교하며 정리하려고 한다. 

 

filter는 DispatcherServelt에 닿기 전에 coarse-grained tasks를 이상적으로 만들어 요청을 낚아챈다. 

 

coarse-grained task에는 다음이 있다.

 

  • 인증
  • Logging과 auditing(Auditing은 JPA에서 사용한거 같은데 신기하네)
  • 이미지와 데이터 압축
  • spring mvc 와 연결되지 않길 원하는 아무 기능

핸들러 인터셉터(Handler Interceptor)는 반면에 디스패처 서블릿과 컨트롤러들 사에의 요청을 낚아챈다. Spring mvc framework 내에서 실행되며 Handler와 ModelAndView 객체에 접근성을 제공한다. fine-grained 기능에 도움이 되고 중복을 줄인다. 

 

  • app 로깅 같은 cross-cutting 문제 관리
  • 자세한 인증 체크
  • 스프링 context와 model 조작

출처 : HandlerInterceptors

 

* fine-grained vs coars-grained

참고 : https://wooono.tistory.com/330