AOP를 공부하게 되면 뒤따로오는 개념인 필터와 인터셉터. 인터셉터를 오늘 처음으로 어떤 것인지에 대해 공부하게 됐는데, AOP와 비슷하다 생각했다. 그래서 AOP와 인터셉터의 차이점에 대해 블로깅하면서 필터도 함께 알아볼 생각이다.
공통 기능 구현의 분리
웹 개발을 하다 보면 로그인 관련(세션처리), 로깅, 트랜잭션, 권한체크 등 공통 로직으로 처리해야 되는 업무가 생긴다.
이러한 기능을 반복해서 작성해야 한다면, 중복된 코드가 많아지게 되고, 유지보수가 힘들어지며 소스관리가 되지 않는다. 때문에 공통 기능은 핵심 기능과 분리하여 관리해야 한다!
그럼 어떻게 공통 기능을 관리해야 할까?
메소드 호출 앞, 중간, 뒤에 추가하여 공통 로직을 처리할 수 있는 방법이 3가지가 있다.
- Filter(필터) - 핸들러 동작의 전 후 과정에 부가로직 처리, 웹 컨테이너에서 관리
- Interceptor(인터셉터) - 이하 비슷함, 스프링 컨테이너에서 관리
- AOP(관점 지향 프로그래밍) - 메서드 동작의 전 후 과정에 부가로직 처리
그럼 어떤 상황에서 이 세가지 중 하나를 선택해서 사용해야 할까? 그 차이점에 대해 알아보자
Filter, Intercepter, AOP
Interceptor와 Filter는 Servlet 단위에서 실행된다. 반면, AOP는 메소드 앞에 Proxy패턴의 형태로 실행된다.
실행 순서를 보면 Filter가 가장 밖에 있고, 그 안에 Interceptor, 그 안에 AOP가 있는 형태이다. 따라서 요청이 들어오면, Filter -> Intercepter -> AOP -> Intercepter -> Filter 순으로 거치게 된다.
이런 구조를 볼 때, Filter와 Intercepter, AOP는 존재하는 영역이 다르며, 호출 순서도 다르다는 것을 확인할 수 있다.
1. 서버를 실행시켜 서블릿이 올라오는 동안에 init이 실행되고, 그 후 doFilter가 실행된다.
2. 컨트롤러에 들어가기 전 preHandler가 실행된다
3. 컨트롤러에서 나와 postHandler, after Completion, doFilter 순으로 진행이 된다.
4. 서블릿 종료 시 destroy가 실행된다.
Filter
스프링의 기능이 아닌 자바 서블릿에서 제공하는 기능(J2EE의 스펙)이다. 스프링에 들어온 요청이 DispatcherServlet에 의해 컨트롤러에 매핑되는데 Filter는 그 전, 후에 동작한다. Filter는 FilterChain을 통해 여러 필터가 연쇄적으로 동작하게 할 수 있다. ServletRequest 혹은 ServletResponse를 교체할 수 있다.
Filter는 주로 XSS방어, 인코딩 변환처리, 요청에 대한 인증, 권한 체크등을 하는데에 쓰인다. 들어온 요청이 DispatcherServlet에 전달되기 전, 헤더를 검사해 인증 토큰이 있는지 없는지, 올바른지 올바르지 않은지 등을 검사할 수 있다.
<filter>
<filter-name>encodingFilter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
필터 클래스는 servlet의 Filter 인터페이스를 구현하여 만들 수 있다. 필터 인터페이스는 3가지 메소드를 가지고 있는데, 다음과 같다.
- init() : 필터 가 생성될 때 수행되는 메소드
- doFilter() : Request, Response가 필터를 거칠 때 수행되는 메소드
- destroy() : 필터가 소멸될 때 수행되는 메소드
Intercepter
요청에 대한 작업을 DispatcherServlet과 Handler(Controller)사이에서 전/ 후로 인터셉터 말 그대로 낚아챌 수 있다. 서버에 들어온 Request 객체를 컨트롤러의 핸들러로 도달하기 전에 낚아채서 부가적인 기능이 실행되게끔 만들어준다.
스프링의 기술이며 Controller 동작 전 후로 동작한다. Filter와의 차이점은 Intercepter가 스프링의 기술이기 때문에 스프링에서 관리하는 빈들을 사용할 수 있다.
인터셉터는 여러 개를 사용할 수 있으며 로그인 체크, 권한 체크, 프로그램 실행시간 작업, 로그확인 등의 업무에서 사용가능하다.
// 이런식으로 사용가능
public class AuthCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
HttpSession session = request.getSession(false);
if(session != null){
Object authInfo = session.getAttribute("authInfo");
if(authInfo != null){
return true; // 로그인 상태
}
}
response.sendRedirect(request.getContextPath() + "/login");
return false; // 로그인 상태 아님
}
}
preHandler()외에도 컨트롤러 메소드 실행 후, view 페이지가 렌더링 되기전에 실행되는 postHanler(), view 페이지가 렌더링 되고 난 후에 적용되는 afterCompletion() 메소드를 제공해주고 있다.
AOP
AOP는 OOP를 보완하기 위해 나온 개념으로 관점 지향 프로그래밍이라 불린다. 객체 지향 프로그래밍을 했을 때 중복을 줄일수 없는 부분을 줄이기 위해 종단면에서 바라보고 처리한다.
주로 로깅, 트랜잭션, 에러처리에 사용되며, Filter와 Intercepter와 다르게 비즈니스 로직을 처리할 때 사용된다. 메소드 전 후로 자유롭게 설정할 수 있다.
InterCepter, Filter는 주소로 대상을 구분해서 걸러내야하는 반면, AOP는 주소, 파라미터, 애노테이션 등 다양한 방법으로 대상을 지정할 수 있다.
AOP의 Advice와 HandlerIntercepter의 가장 큰 차이는 파라미터의 차이다. Advice의 경우 JoinPoint나 ProceedingJoinPoint 등을 활용해서 호출하지만, HandlerIntercepter는 FIiter와 유사하게 HttpServletRequest, HttpServletResponse를 파라미터로 사용한다.
자세한 내용은 따로 다루지 않겠다. 노션이나 티스토리 블로그에 이미 블로깅 해놓았음..
오늘 정리한 내용은 실제 기술면접에서도 나오는 주제라 한다. 잘 알아두어야 할 것 같다.
Reference
https://goddaehee.tistory.com/154
https://gardeny.tistory.com/35
https://jake-seo-dev.tistory.com/83
'Spring > 개념' 카테고리의 다른 글
[Spring] 스프링 AOP (0) | 2023.05.11 |
---|---|
[Spring Security] 스프링 시큐리티의 동작 구조 (0) | 2023.05.11 |
[Spring Security] 스프링 시큐리티와 FilterChain (1) | 2023.05.11 |
[Spring] Spring 기초 및 모듈 구성, Sprig VS SpringBoot (0) | 2023.05.02 |
[Spring] 스프링(Spring Framework)의 정의와 특징 (0) | 2023.04.02 |