[SpringBoot] 필터(Filter)와 인터셉터(Interceptor)
왜 필터와 인터셉터가 필요한가?
- 공통업무에 관한 코드를 모든 페이지에 작성하면 중복 코드가 증가하고 서버에 악영향을 끼칠 수 있다.
- 그래서 공통부분을 따로 빼서 관리하기 위해 필터, 인터셉터, AOP를 사용한다.
Spring MVC Life Cyle
필터
필터란?
- 클라이언트 요청이 서블릿으로 가기 전에 먼저 처리할 수 있도록 톰캣(WAS)에서 지원해주는 기능
- 사용자 요청을 검증하고 필요에 따라 데이터를 추가하거나 변조하는 것
- Servlet실행 여부를 결정할 수도 있다.
필터의 역할
DispatcherServlet
이전에 실행되어 요청 내용을 변경하거나, 여러 가지 체크를 수행한다.- 스프링 컨테이너에 존재하는 빈들을 사용할 수 없어 비즈니스 로직과 연관된 작업을 수행할 수 없다.
- Filter 인터페이스를 구현하거나, 다른 Filter 클래스를 상속받아 doFilter()를 구현해 사용한다.
- 한마디로 수문장 🧑✈️
필터는 어디에 쓰이나?
- 대표적으로 인코딩 변환 처리, XSS 방어, LOG, 인증 등을 구현할 때 사용한다.
- 보안 관련 공통 작업
- 모든 요청에 대한 로깅 또는 감사
- 이미지/데이터 압축 및 문자열 인코딩
- 웹 애플리케이션 전반적으로 사용되는 기능
* XSS : 공격자가 입력 가능한 폼에 악의적인 스크립트를 삽입해 희생자 측에서 동작하도록 만들어 악의적인 행위를 수행하는 행위
필터 구조
- 클라이언트에서 보낸 요청 정보는 필터에 의해 정보가 변경되며, 반대로 자원에서 보낸 정보도 필터에 의해 변경된다.
- 보통 클라이언트와 자원 사이에 1개가 존재하지만, 여러 개의 필터가 모여서 하나의 (필터) 체인을 만들 수 있다.
필터 설정
- 어떤 필터가 어떤 자원에 대해 적용한다는 것을 서블릿 컨테이너에 알려주어야 한다.
web.xml파일
<!-- 한글 처리를 위한 인코딩 필터 -->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Filter 인터페이스
init() - 필터 인스턴스 초기화
doFilter() - 실제 처리 로직
destroy() - 필터 인스턴스 종료
Filter 구현
@Component
public class SimpleFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//SimpleFilter 생성
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//SimpleFilter 시작
chain.doFilter(request, response);
//SimpleFilter 종료
}
@Override
public void destroy() {
//SimpleFilter 소멸
}
}
참조
https://javawork.tistory.com/entry/Spring-Filter-Interceptor-AOP
https://yhmane.tistory.com/144
https://popo015.tistory.com/108
https://velog.io/@ljinsk3/Filter-VS-Interceptor
인터셉터
인터셉터란?
DispatcherServlet
에서 Handler Mapping을 지나Controller
사이에서 요청을 가로채서 처리를 해준다.- 스프링 프레임워크에서 자체적으로 제공하는 기능으로 스프링 컨텍스트에서 동작한다.
- DispatcherServlet은 핸들러 매핑을 통해 컨트롤러를 찾는데, 이때 1개 이상의 인터셉터가 등록되어 있다면 순차적으로 인터셉터들을 거쳐 컨트롤러가 실행되도록 하고, 인터셉터가 없다면 바로 컨트롤러를 실행한다.
인터셉터는 어디에 쓰이나?
- 인증/인가 등과 같은 공통 작업
- API 호출에 대한 로깅 또는 감사
Controller
로 넘겨주는 정보(데이터)의 가공- 그래서 보통 로그인 처리에 이용된다!
인터셉터 설정
Servlet-context.xml
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" /> <!-- 이 경로에서 -->
<bean class="com.prgrms.interceptor.MyInterceptor" /> <!-- 구현한 클래스 -->
</mvc:interceptor>
</mvc:interceptors>
인터셉터 인터페이스
preHandle() - 컨트롤러 실행 전
postHandle() - 컨트롤러 호출 후 실행.
afterCompletion() - 모든 작업이 완료된 후에 실행
Interceptor 구현
- 어떤 컨트롤러가 호출했는지에 관한 정보를 Handler를 통해 받아볼 수 있다.
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//controller 요청되기 전에 호출됨
return true; //false이면 controller로 요청 X
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
//컨트롤러 실행된 후 처리됨.
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
//모든 작업이 끝난 후에 처리됨
}
}
참조
https://velog.io/@ljinsk3/Filter-VS-Interceptor
https://harrydony.tistory.com/373
https://khs0806.tistory.com/15
https://mangkyu.tistory.com/173
결론
필터 : 애플리케이션의 비즈니스 로직과 관계없는 작업이 수행됨. 인코딩, 보안 관련 작업.
인터셉터 : 애플리케이션 비즈니스 로직과 관계있는 작업이 수행됨. 로그인 관련 작업.