1. 필터란?


Servlet 2.3 Specifacation(해당 링크 문서의 챕터 6에 나와있음)에 추가된 대표적인 기능 중 하나가 필터입니다.

스펙에는 아래와 같이 설명되어 있습니다.

A filter is a reusable piece of code that transforms either the content of an HTTP request or response and can also modify header information. 

HTTP Request 또는 HTTP Response 내용을 수정할 수 있고, HTTP 헤더 정보 또한 수정할 수 있는 재사용 가능한 코드 조각

 

구조를 보면 다음과 같습니다.

[그림 1] 서블릿 필터 구조 (출처: 자바캔 블로그)

 

위의 그림에서 보여지듯이, 필터는 HTTP 요청이 서블릿으로 가기 전에 먼저 맞닥뜨리는 놈입니다. 한 가지 짚고 넘어가면, Spring MVC의 인터셉터는 HTTP 요청이 DispatcherServlet으로 들어온 후에 처리가 되는 것이고, 필터는 아에 서블릿으로 들어가기 전에 처리되는 것입니다.

 

필터는 아래의 그림과 같이 여러 개를 둘 수 있는데, 이를 필터 체인이라고 부른다.

[그림 2] 필터 체인 구조 (출처: 자바캔 블로그)

 

위와 같이 필터 체인을 구성할 경우, 첫 번째 필터는 클라이언트의 HTTP 요청을 입력 값으로 받지만, 두 번째 필터 이후 부터는 그 전 필터로부터 필터링된 요청 값을 입력 값으로 받습니다.

 

과거에는 이러한 필터를 이용해서 인증(Authentication)과 권한(Authorization)을 체크하는 용도로 많이 사용하였습니다. 그 후로는 필터 대신 Spring 프레임워크의 인터셉터를 이용하는 방식이 많이 사용되었고, 최근에는 OAuth를 이용한 방식을 많이 사용하게 되었습니다.

 

[그림 3] 인증/권한 방식의 변화

 

필터는 인증/권한 체크 외에도 XSS 방어와 같이 클라이언트의 요청에 대해 필터링이 필요하다면 사용될 수 있다.

 

2. 필터의 구현과 사용


필터 만들고 싶다면 java.servlet.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() {}
}

 

서블릿 컨테이너는 사용자가 요청한 자원에 대한 필터가 존재하면 해당 필터의 doFilter() 메서드를 실행합니다.

 

3. 서블릿 컨테이너에 필터 등록하기


당연히 필터를 만든 후에는 해당 필터가 어떤 자원의 요청에 대해 적용될 것인지를 서블릿 컨테이너에 알려줘야 합니다.

표준 서블릿 명세는 웹 애플리케이션과 관련된 설정은 /WEB-INF/web.xml에서 하도록 명시하고 있습니다.

<web-app>
     
  <filter>
    <filter-name>XssFilter</filter-name>
    <filter-class>com.pangtrue.filter.XssFilter</filter-class>
    <init-param>
      <param-name>paramName</param-name>
      <param-value>value</param-value>
    </init-param>
   </filter>
     
   <filter-mapping>
     <filter-name>XssFilter</filter-name>
     <url-pattern>/board/write</url-pattern>
   </filter-mapping>
     
</web-app>

 

4. 필터를 통한 HTTP 요청/응답 값 변환


서블릿으로 요청 값을 전달하기 위해서는 ServletRequest 인터페이스의 구현체를 이용합니다. 대개 서블릿으로의 요청은 HTTP 프로토콜을 사용하기 때문에 ServletRequest 인터페이스의 구현체 중 하나인 HttpServletRequest 클래스를 이용합니다.

 

필터는 요청/응답 값을 변경하는게 목적이므로, 변환된 요청/응답 값을 담기 위한 HttpServletRequestWrapper 클래스를 제공합니다.

 

5. 참고자료


[1] https://javacan.tistory.com/entry/58