공통 프로세스에 대한 고민
자바 웹 개발을 하다보면, 공통적으로 처리해야 할 업무들이 많다.
예를들어 로그인 관련(세션체크)처리, 권한체크, XSS(Cross site script)방어, pc와 모바일웹의 분기처리, 로그, 페이지 인코딩 변환 등이 있다.
api마다 공통 로직을 작성하게 되면 코드 중복으로 인해 관리하기 까다로워지고, 다른 도메인 로직에 섞여들기 때문에 가독성을 해친다.
따라서 공통 로직을 한 곳에 모으고, 선택적으로 적용하는 것이 필요하다.
Spring에서 위와 같은 상황에 적용하기 위한 3가지 방법이 있다.
Filter, Interceptor, AOP의 흐름
- Interceptor와 Filter는 Servlet 단위에서 실행된다. 반면 AOP는 Proxy 패턴으로 실행된다.
- 요청 순서는 Filter -> Interceptor -> AOP -> Interceptor -> Filter 순으로 거친다.
Filter
서블릿 필터는 DispatcherServlet 이전에 실행이 된다. 서블릿 단에서 제공하는 객체에 접근할 수 있으며, 주로 자원의 앞단에서 요청 내용을 변경하거나, 여러 체크를 수행할 수 있다.
또한 자원의 처리가 끝나고 응답 내용에 대해서 변경할 수 있다.
WebConfig을 빈으로 등록하고, 필터를 추가할 수 있다.
@Configuration
public class WebConfig{
@Bean
public FilterRegistrationBean MyFilter(){
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new MyFilter()); //필터 객체 등록
filterRegistrationBean.setOrder(1); //필터 순서를 지정할 수도 있다.
filterRegistrationBean.addUrlPatterns("/*"); //URL 패턴을 지정할 수도 있다.
return filterRegistrationBean;
}
}
...
//필터 인터페이스를 override 해야 한다.
public class MyFilter implements Filter{
@Override
public void doFilter(...){} //필터에서 수행할 동작을 정의한다.
}
한계: 서블릿 단에서 호출되기 때문에 의존이 있는 Bean들을 사용할 수 없다.
Interceptor
- 디스패처 서블릿과 컨트롤러 사이에서 컨트롤러 호출 직전에 호출됨.
- 모든 Bean들이 다 올라온 후에 호출이 되므로, 의존 주입이 가능하다.
스프링 인터셉터를 사용하려면 HandlerInterceptor 인터페이스를 구현하면 된다.
각 메서드에 따라 요청을 처리하기 전, 후 등을 구분하여 처리할 수 있다.
@Configuration
public class WebConfig implements WebMvcConfiguerer{
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new MyInterceptor()) //인터셉터 추가
.order(1) //순서 설정
.addPathPatterns("/**") //모든 URL에 대해 적용
.excludePathPatterns("/css/**", "/*.ico"); //제외 URL을 설정
}
}
...
public class MyInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(...){
//요청을 가로채어 동작 수행
}
}
AOP
OOP를 보완하기 위해 나온 개념
객체 지향의 프로그래밍을 했을 때 중복을 줄일 수 없는 부분을 줄이기 위해 종단면(관점)에서 바라보고 처리한다.
주로 '로깅', '트랜잭션', '에러 처리'등 비즈니스단의 메서드에서 조금 더 세밀하게 조정하고 싶을 때 사용합니다.
Interceptor나 Filter와는 달리 메소드 전후의 지점에 자유롭게 설정이 가능하다.
Interceptor와 Filter는 주소로 대상을 구분해서 걸러내야하는 반면, AOP는 주소, 파라미터, 애노테이션 등 다양한 방법으로 대상을 지정할 수 있다.
AOP의 Advice와 HandlerInterceptor의 가장 큰 차이는 파라미터의 차이다.
Advice의 경우 JoinPoint나 ProceedingJoinPoint 등을 활용해서 호출한다.
반면 HandlerInterceptor는 Filter와 유사하게 HttpServletRequest, HttpServletResponse를 파라미터로 사용한다.
AOP의 포인트컷
@Before: 대상 메서드의 수행 전
@After: 대상 메서드의 수행 후
@After-returning: 대상 메서드의 정상적인 수행 후
@After-throwing: 예외발생 후
@Around: 대상 메서드의 수행 전/후
'Spring' 카테고리의 다른 글
SpringBoot 중요한 설정 숨기기 (0) | 2022.01.12 |
---|---|
SpringSecurity + CustomAuthenticationProvider 만들기 (0) | 2022.01.11 |
오늘의 질문: jpql 프로젝션 대상이 둘 이상이면 반환 값을 어떻게 받나? (0) | 2021.11.05 |
오늘의 질문 : JPA 엔티티 수정 방식 (0) | 2021.08.10 |
DDD를 위한 일대다 연결관계 매핑 (0) | 2021.08.09 |