1-1. 스프링부트에서 Interceptor의 동작원리를 이해하기 위해서는 먼저 Interceptor가 무엇인지 알아야 한다.
1-2. Interceptor의 주요 동작 과정을 살펴보자
클라이언트로부터 들어오는 요청(HttpRequest)을 가로챈다.
가로챈 요청에 대해 원하는 처리(예: 로그인 체크, 권한 체크 등)를 수행한다.
처리가 끝난 후, 요청을 원래의 목적지인 컨트롤러로 전달한다.
컨트롤러가 응답(HttpResponse)을 반환하면, 이 응답 역시 가로챌 수 있다.
가로챈 응답에 대해 원하는 처리(예: 응답 로깅 등)를 수행한 후, 응답을 클라이언트로 전달한다.
이러한 동작을 통해 Interceptor는 요청과 응답 사이에 원하는 로직을 삽입할 수 있게 해준다. 이를 통해 반복적인 코드를 제거하고, 코드의 중복을 최소화하는 등의 장점을 얻을 수 있다.
2-1. 먼저, 인터셉터를 설정하는 방법부터 살펴보자.
<!-- Interceptors -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.victolee.interceptor.MyInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
2-2. 다음으로, 인터셉터를 구현하는 방법을 살펴보자.
public class MyInterceptor implements HandlerInterceptor {
// controller로 보내기 전에 처리하는 인터셉터
// 반환이 false라면 controller로 요청을 안함
// 매개변수 Object는 핸들러 정보를 의미한다. ( RequestMapping , DefaultServletHandler )
@Override
public boolean preHandle(
HttpServletRequest request, HttpServletResponse response,
Object obj) throws Exception {
System.out.println("MyInterCeptor - preHandle");
return false;
}
// controller의 handler가 끝나면 처리됨
@Override
public void postHandle(
HttpServletRequest request, HttpServletResponse response,
Object obj, ModelAndView mav)
throws Exception {
}
// view까지 처리가 끝난 후에 처리됨
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response,
Object obj, Exception e)
throws Exception {
}
}
2-3. 마지막으로, 로그인 처리를 위한 인터셉터를 구현하는 예제를 살펴보자
public class AuthLoginInterceptor extends HandlerInterceptorAdapter {
@Autowired
private UserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
String email = request.getParameter("email");
String pwd = request.getParameter("pwd");
UserVO vo = new UserVO();
vo.setEmail(email);
vo.setPwd(pwd);
userService.getUser(vo);
return false;
}
}
위의 코드에서는 AuthLoginInterceptor가 HandlerInterceptorAdapter를 상속받아 preHandle 메서드를 오버라이딩 하여 로그인 처리를 수행한다.
클라이언트가 로그인 버튼을 눌렀을 때 email과 pwd를 전달한다고 가정하면, getParameter 메서드로 데이터를 가져올 수 있고 UserVO를 Service 계층에 전달하여 해당 유저가 존재하는지 확인한다.
이렇게 인터셉터를 활용하면, 로그인 처리와 같은 반복적인 작업을 컨트롤러에서 분리하여 코드의 중복을 줄이고 관리를 용이하게 할 수 있다.
3-1. 먼저, HandlerInterceptor 인터페이스를 구현하는 LoggerInterceptor 클래스를 만들어보자
package com.study.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
public class LoggerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.debug("===============================================");
log.debug("==================== BEGIN ====================");
log.debug("Request URI ===> " + request.getRequestURI());
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.debug("==================== END ======================");
log.debug("===============================================");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
}
위의 LoggerInterceptor 클래스는 HandlerInterceptor 인터페이스를 구현하고 있으며, preHandle 메서드와 postHandle 메서드를 오버라이드하고 있다.
preHandle 메서드는 컨트롤러가 호출되기 전에 실행되며, postHandle 메서드는 컨트롤러가 실행된 후에 호출됩니다. 이 예시에서는 각 메서드에서 로그를 출력하도록 구현하였다.
3-2. 다음으로, WebMvcConfigurer 인터페이스를 구현하는 WebMvcConfig 클래스를 만들어보자. 이 클래스에서 인터셉터를 등록한다.
package com.study.config;
import com.study.interceptor.LoggerInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggerInterceptor())
.excludePathPatterns("/css/**", "/images/**", "/js/**");
}
}
위의 WebMvcConfig 클래스는 WebMvcConfigurer 인터페이스를 구현하고 있으며, addInterceptors 메서드를 오버라이드하고 있다. addInterceptors 메서드에서는 LoggerInterceptor를 등록하고, 특정 패턴의 경로를 인터셉터의 적용에서 제외하고 있다.
이렇게 설정하면, 인터셉터가 정상적으로 동작하게 된다. 이 예시에서는 모든 요청에 대해 요청 URI를 로그로 출력하게 된다. 참고로, 이 예시는 스프링 부트 2.x 버전을 기준으로 작성되었다. 스프링 부트 3에서도 동일하게 적용할 수 있다.