스프링 프로젝트를 진행하다 보면 controller에 접근전 공통적으로 처리해야 하는 로직이 있었을 것이다. controller로 이동하기 전에 로그인 정보를 확인한다든지, 보안토큰, 불필요한 파라미터나 파일 등을 전송 중인지 미리 확인하면 좋은데 이러한 상황에서 사용하는 것이 필터와 인터셉터이다.
필터와 인터셉터는 비슷한 기능을 하지만 차이가 존재한다. 아래 사진을 봐보자.
위 사진과 같이 스프링 프로젝트에서 요청이 와서 스프링 MVC를 사용하고 DispatcherServlet에 앞에서 처리를 하면 필터이고 뒤에서 처리하면 인터셉터이다.
아래는 좀 더 필터와 인터셉터의 구체적인 부분들이다.(출처: https://velog.io/@ansalstmd/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%EB%8B%A4%EC%96%91%ED%95%9C-%EA%B8%B0%EB%8A%A5-5.-Spring-Boot-Filter%EC%99%80-Interceptor )
- Filter란 Web Application에서 관리되는 영역으로써 Spring Boot Framework에서 Client로부터 오는 요청/응답에 대해서 최초/최종 단계의 위치에 존재하며, 이를 통해서 요청/응답의 정보를 변경하거나, Spring에 의해서 데이터가 변환되기 전의 순수한 Client의 요청/응답 값을 확인할 수 있다
- 유일하게 ServletRequest, ServletResponse의 객체를 변환할 수 있다
- 주로 Spring Framework에서는 request/response의 logging 용도로 활용하거나, 인증과 관련된 Logic들을 해당 Filter에서 처리한다
- 이를 선/후 처리 함으로써, Service business logic과 분리시킨다
- Interceptor란 Filter와 매우 유사한 형태로 존재 하지만, 차이점은 Spring Context에 등록
- AOP와 유사한 기능을 제공할 수 있으며, 주로 인증 단계를 처리하거나, Logging를 하는 데 사용한다
- 이를 선/후 처리 함으로써, Service business logic과 분리시킨다
그렇다면 이제 간단하게 프로젝트에 적용해 보겠다.
먼저 interface HandlerInterceptor를 상속받아서 Interceptor를 구성한다.
package calender.calender.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Log4j2
@Component
public class Interceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
String url = request.getRequestURI();
log.info("request url : {}", url);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
-preHandler : 컨트롤러에 도착하기 전에 동작하는 메서드로 return값이 true이면 진행, false이면 멈춘다.
-postHandler : 컨트롤러에 도착하여 view가 랜더링 되기 전에 동작한다.
-afterCompletion: view가 정상적으로 랜더링 된 후에 마지막에 실행된다.
위에서는 preHandler안에 uri 로그를 출력하도록 하였다.
이제 작성한 인터셉터를 등록해야 하는데 아래와 같이 구현한다.
package calender.calender.config;
import calender.calender.controller.Interceptor;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@RequiredArgsConstructor
public class ServerConfig implements WebMvcConfigurer {
private final Interceptor interceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptor).addPathPatterns();
}
}
위와 같이 WebMvcConfigurer를 상속받아 addIntercepotrs를 통해 사용할 Interceptor를 등록하고. 패턴을 등록해준다.
위와 같이 작성한 후 실행하면 아래와 같다.
여기서 특정 주소에만 인터셉터가 동작하도록 할 수 있다.
아래와 같이 작성한다.
package calender.calender.config;
import calender.calender.controller.Interceptor;
import java.util.Arrays;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@RequiredArgsConstructor
public class ServerConfig implements WebMvcConfigurer {
private final Interceptor interceptor;
private static final List<String> URL_PATTERNS = Arrays.asList("/login", "/articles"); //인터셉터가 동작 해야 될 요청 주소 mapping 목록
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptor).addPathPatterns(URL_PATTERNS);
}
}
그렇다면 /login, 과 /articles 에만 인터셉터가 동작할 것이다.
출처
https://congsong.tistory.com/24
https://myhappyman.tistory.com/199
https://elfinlas.github.io/2017/12/28/SpringBootInterceptor/
'Spring' 카테고리의 다른 글
Springboot - 서비스 단위 테스트 (0) | 2023.04.02 |
---|---|
Spring boot - 서버의 존재하지 않는 URL 접근 시 예외 처리 (0) | 2022.04.09 |
스프링부트 AOP에 대한 기본 정리 (0) | 2022.02.28 |
Spring Controller를 REST 방식으로 변화 - Rest API (0) | 2022.02.23 |
스프링 MVC에 대한 간단 정리 (0) | 2022.02.09 |