Spring

[Spring Boot] 스프링 인터셉터 (Spring Interceptor)

2023. 4. 21. 21:02
목차
  1. Spring Interceptor
  2. 1) 스프링 인터셉터 흐름
  3. 2) 스프링 인터셉터 제한
  4. 3) 스프링 인터셉터 체인
  5. interface HandlerInterceptor
  6. Configuration
  7. 예제
  8. 예제 1) 로그 인터셉터
  9. 예제 2) 로그인 체크 인터셉터
  10. WebConfig 등록

Spring Interceptor


스프링 인터셉터는 스프링 MVC가 제공하는 웹과 관련된 공통 관심사항을 효과적으로 해결할 수 있는 기술이다.


예를 들어 로그인되지 않은 사용자가 로그인해야지만 접근할 수 있는 페이지에 접근하려 할 때,
세션을 확인하여 세션에 로그인된 사용자의 유무에 따라 접근 허용 여부를 설정해 줄 수 있다.


1) 스프링 인터셉터 흐름

HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러
  • 서블릿 필터는 서블릿이 호출되기 이전에 호출된다.
  • 스프링 인터셉터는 컨트롤러 호출 직전에 호출된다.
  • URL패턴을 서블릿 필터에 비해 정밀하게 설정할 수 있다.

2) 스프링 인터셉터 제한

1. 접근 허용 시

HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러

2. 접근 거절 시

HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터(접근 거부, 컨트롤러 호출 x) -> 종료

3) 스프링 인터셉터 체인

스프링 인터셉터는 체인으로 구성되고, 순서를 자유롭게 변경할 수 있다.

HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 인터셉터 1 -> 인터셉터 2... -> 컨트롤러

 


 

interface HandlerInterceptor


preHandle

  • 컨트롤러 호출 전
  • return true : 다음 인터셉터 또는 컨트롤러가 호출된다.
  • return false : 다음이 호출되지 않고 종료된다.

postHandle

  • 컨트롤러에서 예외가 발생하면 호출되지 않는다.

afterCompletion

  • 요청 완료 이후 항상 호출된다.
  • 예외 발생 시 예외 [ Exception ex ]를 파라미터로 받아서 예외 정보를 로그로 출력할 수 있다.
3개의 메서드 중 원하는 것만 구현해서 사용하면 된다.
public interface HandlerInterceptor {

    default boolean preHandle(HttpServletRequest request, 
                              HttpServletResponse response,
                              Object handler)throws Exception { return true;}

    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 { }

 


 

Configuration


HandlerInterceptor를 implements 하여 메서드를 구현한 클래스를 만든 뒤,

WebConfig를 만들어서 addInterceptors 메서드를 구현해야 한다.

 

addInterceptors 메서드 내에 registry.addInterceptor를 통해 인터셉터를 추가하면 된다.

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       registry.addInterceptor(/*인터셉터 생성*/)
                .order(1) //첫번째로 실행 될 인터셉터로 등록
                .addPathPatterns(/*URL 경로*/) 
                .excludePathPatterns(/*제외할 URL 경로*/);
    }
}
  • . order(int n) : n번째로 실행할 인터셉터로 등록
  • . addPathPatterns() : ( ) 하위에 전부 적용
  • . excludePathPatterns 등록되었지만, 그중 제외할 URL 지정

 


 

예제


예제 1) 로그 인터셉터

@Slf4j
public class LogInterceptor implements HandlerInterceptor {

    public static String LOG_ID = "logId";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
                             Object handler) throws Exception {

        String requestURI = request.getRequestURI();
        String uuid = UUID.randomUUID().toString(); // uuid 생성
        
        request.setAttribute(LOG_ID,uuid); //afterCompletion에서 사용하기위해 request에 넣는다.

        //@RequestMapping을 사용하는 경우 : HandlerMethod가 사용된다.
        //정적 리소스를 사용하는 경우 : ResourceHttpRequestHandler 가 사용된다.
        if(handler instanceof HandlerMethod){
            HandlerMethod hm = (HandlerMethod) handler;
            //HandlerMethod의 여러가지 메소드를 사용하여 호출할 컨트롤러 메서드의 정보를 얻을 수 있다.
        }
        log.info("----------new REQUEST------------");
        log.info("REQUEST [{}][{}] | uuid : [{}]", requestURI, handler, uuid);

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, 
                            Object handler, ModelAndView modelAndView) throws Exception {

        log.info("postHandler [{}]", modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
                                Object handler, Exception ex) throws Exception {

        String requestURI = request.getRequestURI();
        //위의 preHandle에서 생성한 uuid를 request에 넣어뒀던것을 가져온다.
        String uuid = (String) request.getAttribute(LOG_ID); 

        log.info("RESPONSE [{}][{}] | uuid : [{}]", requestURI, handler, uuid);

        //오류발생시 오류 로그도 찍어주자.
        if(ex!=null){
            log.error("afterCompletion error!!", ex);
        }
    }
}

예제 2) 로그인 체크 인터셉터

preHandle만 필요해서 필요한 것만 구현했다.

@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();//request에서 session을 가져온다
        // 세션이 비어있거나, 세션에서 "loginId"가 비어있을때 접근 거부를 위한 로직
        if(session == null || session.getAttribute("loginId") == null){
            log.info("미인증 사용자 요청");
            // [redirectURL=(requestURI)&msg=true] 라는 쿼리를 달아서 로그인 화면으로 redirect한다.
            response.sendRedirect("/login?redirectURL="+requestURI+"&msg=true");
            //false 반환 시 다음 인터셉터가 호출되지 않는다.
            return false;
        }

        return true;
    }
}

WebConfig 등록

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LogInterceptor())
                .order(1) //첫번째로 실행 될 인터셉터로 등록
                .addPathPatterns("/**") //  "/"하위에 전부 적용
                .excludePathPatterns("/css/**","/*.ico","/error");

        registry.addInterceptor(new LoginCheckInterceptor())
                .order(2) //두번째로 실행 될 인터셉터로 등록
                .addPathPatterns("/**")
                .excludePathPatterns("/","/member/add","/board","/board/post/*","/login",
                                "/logout","/css/**","/*.ico","/error");
    }
}
  • "/**" : / 하위의 모든 경로
  • "/board" : 정확히 '/board'만 해당
  • /css/** : /css로 시작하는 모든 경로
  • /*. ico 끝나는 경로 제외
  • /board/post/* : /board/post/(숫자)인 경로

 


(참고) 김영한 님 인프런 Spring MVC-2
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-

 

반응형

'Spring' 카테고리의 다른 글

[Spring Boot] PRG 패턴 ( Post - Redirect - Get )  (1) 2023.04.21
[Spring] 로깅 logging (@Slf4j)  (0) 2023.04.21
[Spring Boot] @PathVariable과 @RequestParam - 파라미터 받기  (0) 2023.04.21
[Spring] Bean Validation  (0) 2023.04.21
[Spring] 메시지, 국제화  (0) 2023.04.21
  1. Spring Interceptor
  2. 1) 스프링 인터셉터 흐름
  3. 2) 스프링 인터셉터 제한
  4. 3) 스프링 인터셉터 체인
  5. interface HandlerInterceptor
  6. Configuration
  7. 예제
  8. 예제 1) 로그 인터셉터
  9. 예제 2) 로그인 체크 인터셉터
  10. WebConfig 등록
'Spring' 카테고리의 다른 글
  • [Spring] 로깅 logging (@Slf4j)
  • [Spring Boot] @PathVariable과 @RequestParam - 파라미터 받기
  • [Spring] Bean Validation
  • [Spring] 메시지, 국제화
HSRyuuu
HSRyuuu
Web Backend Developer happyhsryu
HSRyuuu
HS_dev_log
HSRyuuu
전체
오늘
어제
  • 전체 글 보기 (233)
    • Java (25)
    • Spring (27)
    • JPA & QueryDSL (13)
    • Database (17)
    • 자료구조 & 알고리즘 (30)
    • DevOps (10)
    • [ Computer Science ] (47)
      • Web & Network (14)
      • 프로그래밍 이론 (11)
      • 운영체제 (3)
      • 데이터베이스 이론 (5)
      • Linux 리눅스 (7)
    • [ Frontend ] (17)
      • Vue.js & Nuxt.js (9)
      • JSP_Thymeleaf (7)
    • [ 기타 ] (47)
      • 오픈소스 라이브러리 (5)
      • 코딩테스트 (13)
      • Trouble Shooting (7)
      • Tech Interview (6)
      • Book Review (9)
      • 끄적끄적... (5)
      • 개인 프로젝트 (2)

블로그 메뉴

  • 홈
  • 태그
  • github

공지사항

  • GitHub
  • 공부한 내용을 정리하고 기록하는 블로그 입니다.

인기 글

태그

  • Java
  • 백엔드공부
  • Linux
  • 자료구조
  • 백엔드
  • 기술면접
  • Redisson
  • vue3
  • SpringBoot
  • 백준
  • Database
  • mybatis
  • 트랜잭션
  • 클린코드
  • JPA
  • 개발자
  • springsecurity
  • 리눅스
  • TechInterview
  • cleancode
  • Nuxt3
  • 백엔드스쿨
  • MySQL
  • 백엔드기술면접
  • Redis
  • Spring
  • HTTP
  • SQL
  • web
  • 제로베이스

최근 댓글

최근 글

hELLO · Designed By 정상우.
HSRyuuu
[Spring Boot] 스프링 인터셉터 (Spring Interceptor)
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.