이 글은 Spring과 Filter - Interceptor(1)과 이어진다.
개념을 좀 더 쉽게 이해해보자
요청에 대한 작업 전 / 후에서 가로챈다고 보면 된다.
필터는 스프링 컨텍스트 외부에 존재하며 스프링과 무관한 자원에 대해 동작한다.
하지만 인터셉터는 스프링의 DispatcherServlet이 컨트롤러를 호출하기 전 / 후로 끼어들기 때문에 스프링 Context 내부에서 Controller(Handler)에 관한 요청과 응답에 대해 처리한다.
스프링의 모든 빈 객체에 접근할 수 있으며, 여러 개의 인터셉터 사용이 가능하다.
예시로 로그인 체크, 권한체크, 프로그램 실행시간 계산작업, 로그확인 등의 업무를 처리할 수 있다.
하나씩 이해해보자 - Interceptor
Interceptor란 Filter와 매우 유사한 형태로 존재하지만, 차이점은 Spring Context에 등록된다.
AOP와 유사한 기능을 제공할 수 있으며, 주로 인증 단계를 처리 하거나, Logging을 하는데에 사용된다.
이를 선 / 후 처리 함으로써 Service Business Logic과 분리시킨다.
[실행 메소드]
- preHandler() - 컨트롤러 메소드가 실행되기 전
- postHandler() - 컨트롤러 메소드 실행 직후 view 페이지가 렌더링 되기 전
- afterCompletion() - view 페이지가 렌더링 되고 난 후
[예시코드]
: 아래 코드를 통해 해당 요청의 경로를 보여주며, private으로 들어오면 has Annotation이 true로 보이도록 한다.
(1) PublicController
@RestController
@RequestMapping("/api")
public class PublicController {
@GetMapping("/hello")
public String hello(){
return "public hello";
}
}
(2) PrivateController
@RestController
@RequestMapping("/api/private")
@Auth
@Slf4j
public class PrivateController {
@GetMapping("/hello")
public String hello(){
return "private hello";
}
}
보다시피 PublicController와는 다르게 Auth Annotation이 붙여있다.
(3) InterceptorApplication
@SpringBootApplication
public class InterceptorApplication {
public static void main(String[] args) {
SpringApplication.run(InterceptorApplication.class, args);
}
}
(4) MvcConfig
@Configuration
@RequiredArgsConstructor
public class MvcConfig implements WebMvcConfigurer {
private final AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(authInterceptor);
}
}
(5) AuthInterpretor
@Slf4j
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String url = request.getRequestURI();
log.info("request URL : {}", url);
boolean hasAnnotation = checkAnnotation(handler, Auth.class);
log.info("has annotation : {}", hasAnnotation);
return true;
}
private boolean checkAnnotation(Object handler, Class clazz){
// resuorce에 대한 요청일때는 통과 ex : javascript, html..
if(handler instanceof ResourceHttpRequestHandler){
return true;
}
// annotation이 달려있나 확인
HandlerMethod handlerMethod = (HandlerMethod) handler;
if(null != handlerMethod.getMethodAnnotation(clazz)|| null != handlerMethod.getBeanType().getAnnotation(clazz)){
return true;
}
return false;
}
}
[결과]
2021-08-16 04:50:12.570 INFO 1801 --- [nio-8080-exec-1] c.e.i.interceptor.AuthInterceptor : request URL : /api/hello
2021-08-16 04:50:12.571 INFO 1801 --- [nio-8080-exec-1] c.e.i.interceptor.AuthInterceptor : has annotation : false
2021-08-16 04:50:17.270 INFO 1801 --- [nio-8080-exec-3] c.e.i.interceptor.AuthInterceptor : request URL : /api/private/hello
2021-08-16 04:50:17.270 INFO 1801 --- [nio-8080-exec-3] c.e.i.interceptor.AuthInterceptor : has annotation : true
위의 두 줄 로그는 public으로 요청했을때며, 아래는 private으로 요청했을때다.
Filter, Interceptor, AOP의 차이
Interceptor는 스프링 Context 내부에서 Controller(Handler)에 관한 요청과 응답에 대해 처리한다.
반면 Filter는 Web Application 영역에서 동작된다.
Filter, Interpretor와 달리 AOP는 메소드 전 후의 지점에서 보다 자유롭게 설정이 가능하다.
Filter, Interceptor는 주소로 대상을 구분해서 걸러내야하는 반면, AOP는 주소, 파라미터, 어노테이션 등 다양한 방법으로 대상을 지정할 수 있다.
참고 출처
김백개발자 - [카카오 면접] Spring Filter, Interceptor, AOP
코딩병원 - [Spring] Filter, Interceptor, AOP개념과 차이점
'👩🏻💻 Programming > SpringBoot' 카테고리의 다른 글
RestTemplate (0) | 2021.08.16 |
---|---|
Spring과 비동기 처리 (0) | 2021.08.16 |
SpringBoo와 Filter, 그리고 Interceptor (1) (0) | 2021.08.16 |
Spring Boot와 Validation (1) (0) | 2021.08.11 |
Bean vs Component (0) | 2021.08.10 |