-
[3] Filter심층분석 2024. 3. 12. 18:10728x90
Filter란
filter client의 요청과 응답을 정제하는 역할인데, Dispatcher Servlet에 요청이 전달되기 전 / 후에 url 패턴에 맞는 모든 요청에 대해 부가 작업을 처리할 수 있는 기능을 제공합니다. ( 다중 필터가 모여 체인을 형성할 수 있습니다. )
즉, 필터는 스프링의 독자적인 기능이 아니라 톰캣과 같은 웹 컨테이너에 의해 관리가 되는 것이고, 스프링 범위 밖에서 처리되는 것이다.
주로 Filter는 요청에 대한 인증, 권한 체크등에 사용됩니다.
구체적으로 들어온 요청이 디스패치 서블릿에 전달하기 전에 검사해 인증 토큰 유무 / 유효성 검사를 합니다.
( 저는 프로젝트 구현할때 JWT를 구현하는데 있어서 사용하였습니다. )https://github.com/T-Notes/Tnote-BackEnd/blob/main/src/main/java/com/example/tnote/base/filter/JwtAuthenticationFilter.java
https://github.com/j9972/health-genie/tree/master/src/main/java/com/example/healthgenie/base/filter
Filter 인터페이스의 주요 메소드
public interface Filter { public default void init(FilterConfig filterConfig) throws ServletException {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; public default void destroy() {}
Filter은 이렇게 3가지의 메소드를 가지고 있습니다.
1. init() :
필터 객체를 초기화하고 서비스에 추가하기 위한 메소드이다.
웹 컨테이너가 1회 init()을 호출하여 필터 객체를 초기화하면 이후 요청들은 doFilter()를 통해 처리된다.
2. doFilter() :
url-pattern에 맞는 모든 HTTP 요청이 디스패처 서블릿으로 전달되기 전에 웹 컨테이너에 의해 실행되는 메소드이다.
doFilter의 파라미터로 FilterChain이 있는데, FilterChain의 doFilter 통해 다음 대상으로 요청을 전달할 수 있게 된다.
chain.doFilter()로 전, 후에 우리가 필요한 처리 과정을 넣어줌으로써 원하는 처리를 진행할 수 있다.
3. destroy() :
필터 객체를 제거하고 사용하는 자원을 반환하기 위한 메소드이다.
웹 컨테이너가 1회 destroy()를 호출하여 필터 객체를 종료하면 이후에는 doFilter에 의해 처리되지 않는다.
동작 원리
- Client의 요청 : 웹 요청이 클라이언트로부터 발생
- Filter 전처리 : 도착한 요청은 설정된 Filter 순서대로 전처리를 거친다. 이 과정에서 요청 내용의 수정, 요청 차단 등이 가능하다.
1) LoggingFilter 전처리 : client로부터 요청이 오면 logginFilter가 먼저 동작하고 관련된 로깅작업이 수핸된다.
2) AuthFilter 전처리 : logginFilter 이후, AuthFilter 동작하여 인증 관련 처리를 진행한다.
- server 처리 : 모든 Filter 전처리가 종료되면, 해당 요청은 Controller나 Servlet으로 전달되어 처리된다.
- Filter 후처리 : 처리된 응답은 Filter를 거치면서 후처리 단계를 진행한다. 이 단계에서 응답 내용의 수정이나 추가 작업이 가능하다.
1) AuthFilter 후처리 : Controller나 Servlet의 처리 이후에는 AuthFilter의 후처리 로직이 실행된다.
2) LoggingFilter 후처리 : 마지막으로 loggingFilter의 후처리 로직이 실행되며, 관련된 로깅 작업이 수행된다.
- 응답 반환 : 후처리를 거친 최종 응답이 클라이언트에게 반환된다.
인터셉터와 다른점
1. 필터는 Request, Response 객체를 조작할 수 있지만, 인터셉터는 조작할 수 없다.
- 필터 : doFilter에서 다음 필터를 호출하기 위해서는 필터 체이닝( 다음 필터 호출 ) 을 해주어야 하는데, 이때 Request, Reponse 객체를 넘겨주므로 원하는 객체를 넣어줄 수 있다
- 인터셉터 : 디스패치 서블릿이 여러 인터셉터 목록을 가지며, 순차적으로 실행을 시키는데, true를 반환하면 다음 인터셉터가 실행되거나 컴트롤러로 요청이 전달되며, false를 반환하면 요청이 중단되기에 객체를 넘겨줄 수 없다.
2. 필터 / 인터셉터 통해 사용 사례
- 필터 : 보안 및 인증 / 인가 작업 , 모든 요청에 대한 로깅 또는 검사, 이미지 / 데이터 압축 및 문자열 인코딩
=> 기본적으로 스프링과 무관하게 전역적으로 처리해야 하는 작업들을 처리할 수 있다.
- 인터셉터 : 세부적인 보안 및 인증 / 인가 공통 작업, API 호출에 대한 로깅 또는 검사, Controller로 넘겨주는 정보 가공
=> 클라이언트의 요청과 관련되어 전역적으로 처리해야 하는 작업들을 처리할 수 있다.
3. 실행되는 시점이 다르다.
- 필터 : 디스패치 컨트롤러에 요청이 전달하기 전/후에 url 패턴에 따라 부가 작업을 처리한다
- 인터셉터 : 디스패치 컨트롤이 Controller를 호출하기 전/후로 요청과 응답을 참조 및 가공한다
차이점