들어가기 전에
하기 포스팅은 "스프링부트 시작하기(김인우 저)" 책을 공부하며 적은 포스팅입니다. 이번 포스팅에서는 인터셉터에 대해 살펴보도록 하겠습니다.
인터셉터(Interceptor)
Spring의 인터셉터는 어떠한 URI을 호출했을 때 해당 요청의 컨트롤러가 처리되기 전 또는 후에 작업을 하기 위해 사용됩니다. 이러한 역할은 필터(Filter)와 인터셉터(Interceptor)로 수행할 수 있습니다. 먼저, 필터(Filter)와 인터셉터(Interceptor)의 차이를 알아보겠습니다.
필터(Filter) VS 인터셉터(Interceptor)
- 필터는 디스패처 서블릿 앞 단에서 동작하지만, 인터셉터는 디스패처 서블릿에서 컨트롤러로 가기 전에 동작합니다.
- 필터는 J2EE 표준 스펙에 있는 서블릿 기능 중 일부이지만, 인터셉터는 스프링 프레임워크에서 제공하는 기능입니다.
- 따라서, 인터셉터는 스프링 빈을 사용할 수 있습니다.
- 일반적으로, 문자열 인코딩과 같은 웹 전반에서 사용되는 기능은 필터로 구현하고 클라이언트 요청과 관련이 있는 처리(예: 로그인, 인증, 권한 등)는 인터셉터로 처리합니다.
HandlerInterceptorAdapter로 인터셉터 구현하기
Spring에서 인터셉터는 HandlerInterceptorAdapter 클래스를 상속받아 구현할 수 있습니다.
메소드 | 역할 |
---|---|
preHandle | 컨트롤러 실행 전에 수행됩니다. |
postHandle | 컨트롤러 수행 후 결과를 뷰로 보내기 전에 수행됩니다. |
afterCompletion | 뷰의 작업까지 완료된 후 수행됩니다. |
인터셉터로 원하는 기능을 만들기 위해서는 위 메소드 중 선택하여 인터셉터를 등록하면 됩니다. 여기서는 각 요청의 시작과 끝을 보여주는 로그를 출력해주는 인터셉터를 작성해보겠습니다.
src/main/java/board 패키지 아래에 interceptor 패키지를 생성하고 LoggerInterceptor 클래스를 생성합니다.
LoggerInterceptor.java에 아래와 같이 코드를 작성합니다.
package board.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
@Slf4j
public class LoggerInterceptor extends HandlerInterceptorAdapter{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.debug("==================== START ====================");
log.debug(" Request URI \t: " + request.getRequestURI());
return super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.debug("==================== END ====================");
}
}
위 코드에서 발생 가능한 에러(The type HandlerInterceptorAdapter is deprecated) 해결법
아래와 같이 HandlerIntercepterAdapter에 취소선이 그어지면서 deprecated 에러가 발생할 수 있습니다.
해당 에러가 발생하는 이유는 아래 docs를 보면 알 수 있습니다.
org.springframework.web.servlet.handler.HandlerInterceptorAdapter의 경우 더 이상 사용되지 않는다.
HandlerInterceptor와 AsyncHadlerInterceptor 인터페이스를 implements하여 사용하여야 합니다.
따라서, 위 에러가 발생한다면 아래와 같이 코드를 수정하여 사용하면 됩니다.
package board.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Slf4j
public class LoggerInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.debug("==================== START ====================");
log.debug(" Request URI \t: " + request.getRequestURI());
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.debug("==================== END ====================");
}
}
import org.springframework.web.servlet.HandlerInterceptor
: 기존에 HandlerInterceptorAdapter를 상속할 때와 달리, HandlerInterceptor 인터페이스를 구현하기 위해 import 구문 추가return true
: 기존에 HandlerInterceptorAdapter를 상속할 때는 extends 구문이므로 부모클래스의 preHandle을 반환할 수 있었으나, 인터페이스의 경우 부모의 메소드를 구현하지 않은채 사용할 수 없어 true를 반환하도록 변경public boolean preHandle()
: 컨트롤러가 실행되기 전 수행public void postHandle()
: 컨트롤러 실행된 후 수행
Interceptor 등록하기
앞서 만든 LoggerInterceptor를 스프링 빈으로 등록해보겠습니다. configuration 패키지 안에 WebMvcConfiguration 클래스를 생성하고 아래 내용을 작성합니다.
package board.configuration;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import board.interceptor.LoggerInterceptor;
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggerInterceptor());
}
}
registry.addInterceptor(new LoggerInterceptor())
: 인터셉터를 등록합니다.addPathPatterns()
와excludePathPatterns()
메소드를 이용하여 요청 주소의 패턴과 제외할 요청 주소의 패턴을 지정하여 선택적으로 적용할 수도 있습니다. 현재는 모든 요청에 대해 인터셉터를 적용하므로 따로 패턴 적용하지 않았습니다.
Interceptor 설정 결과 확인하기
SpringBoot 어플리케이션을 실행하고 게시판 목록 호출(/board/openBoardList.do)시, 컨트롤러 호출 앞뒤로 로그가 생성됨을 확인할 수 있습니다.
'FRAMEWORK > Spring' 카테고리의 다른 글
[SpringBoot] 게시판 구현하기 10 (스프링의 다양한 기능 살펴보기 - 트랜잭션) (0) | 2020.12.26 |
---|---|
[SpringBoot] 게시판 구현하기 9 (스프링의 다양한 기능 살펴보기 - AOP) (0) | 2020.12.26 |
[SpringBoot] 게시판 구현하기 7 (스프링의 다양한 기능 살펴보기 - 로그) (1) | 2020.12.25 |
[SpringBoot] 게시판 구현하기 6 (게시글 수정 및 삭제 기능 만들기) (1) | 2020.12.22 |
[SpringBoot] 게시판 구현하기 5 (게시글 상세 화면 만들기) (0) | 2020.12.21 |