[Spring MVC] 스프링 인터셉터
소개
스프링 인터셉터도 서블릿 필터와 같이 웹 관련 공통 관심 사항을 효과적으로 해결할 수 있는 기술이다. 서블릿 필터는 서블릿이 제공하는 기술, 스프링 인터셉터는 스프링 MVC가 제공하는 기술이다.
서블릿 필터와는 적용되는 순서와 범위, 사용법이 다르다.
흐름
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러
- DispatcherServlet과 컨트롤러 사이에서 컨트롤러 호출 직전에 호출된다.
- URL 패턴을 적용할 수 있는데, 서블릿 URL 패턴과는 다르며, 매우 정밀하게 설정할 수 있다.
제한
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러 //로그인 사용자
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터(적절하지 않은 요청, 컨트롤러 호출X) // 비 로그인 사용자
체인
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 인터셉터1 -> 인터셉터2 -> 컨트롤러
인터셉터 인터페이스
public interface HandlerInterceptor {
default boolean preHandle(
HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {}
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 {}
}
- 서블릿 필터는
doFilter()
하나만 제공되지만, 인터셉터는 컨트롤러 호출 전(preHandle
), 호출 후(postHandle
), 요청 완료 이후(afterCompletion
)와 같이 단계적으로 세분화 되어 있다. - 서블릿 필터의 경우
request
,response
만 제공했지만, 인터셉터는 어떤 컨트롤러(handler
)가 호출되는지 호출 정보도 받을 수 있다. - 또한, 어떤
ModelAndView
가 반환되는지 응답 정보도 받을 수 있다.
인터셉터 호출 흐름
정상 흐름
preHandle
: 핸들러 어댑터 호출 전에 호출.preHandle
의 응답값이true
면 진행,false
면 더는 진행하지 않는다.false
인 경우 나머지 인터셉터는 물론이며, 핸들러 어댑터도 호출되지 않는다.
postHandle
: 핸들러 어댑터 호출 후에 호출.afterCompletion
: 뷰가 렌더링 된 이후에 호출.
인터셉터 예외 상황
예외 발생시
postHandle
: 컨트롤러에서 예외 발생시postHandle
은 호출XafterCompletion
:afterCompletion
은 항상 호출된다.- 이 경우 예외를 파라미터로 받아서 로그로 출력할 수 있다.
try-catch
문의finally
같은 느낌.- 예외와 무관하게 공통 처리를 하려면
afterCompletion
을 사용해야 한다.
정리
인터셉터는 스프링 MVC 구조에 특화된 필터 기능을 제공하기 때문에, 스프링 MVC를 사용하고, 특별히 필터를 사용해야 하는 상황이 아니라면 인터셉터를 사용하는 것이 더 편리하다.
인증 체크
LoginCheckInterceptor
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(
HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String requestURI = request.getRequestURI();
log.info("인증 체크 인터셉터 실행 {}", requestURI);
HttpSession session = request.getSession(false);
if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {
log.info("미인증 사용자 요청");
//로그인으로 redirect
response.sendRedirect("/login?redirectURL=" + requestURI);
return false;
}
return true;
}
}
인증은 컨트롤러 호출 전에만 호출되면 되기 때문에 preHandle
만 구현하면 된다.
WebConfig
세밀한 설정 가능
순서 주의, 세밀한 설정 가능
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// LogInterceptor 생략..
registry.addInterceptor(new LoginCheckInterceptor())
.order(2)
.addPathPatterns("/**")
.excludePathPatterns(
"/", "/members/add", "/login", "/logout",
"/css/**", "/*.ico", "/error"
);
}
}
WebMvcConfigurer
가 제공하는 addInterceptors
를 사용해서 인터셉터를 등록할 수 있다.
registry.addInterceptor(...)
: 인터셉터 등록order()
: 인터셉터의 호출 순서 지정. 낮을 수록 먼저 호출된다.addPathPatterns
: 인터셉터를 적용할 URL 패턴을 지정.excludePathPatterns(...)
: 인터셉터에서 제외할 패턴을 지정.
PathPattern 공식 문서 [링크]
‘?’ 한 문자 일치
‘*’ 경로(/) 안에서 0개 이상의 문자 일치
‘**’ 경로 끝까지 0개 이상의 경로(/) 일치
(생략)…
<출처 : 인프런 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술(김영한)>
댓글남기기