[Spring] 스프링 인터셉터

JJoSuk·2023년 6월 11일
0

본 프로젝트 자료는 김영한님의 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술을 참고 제작됐음을 알립니다.

스프링 인터셉터 란?

스프링 인터셉터도 서블릿 필터와 같이 웹과 관련된 관심 사항을 처리한다.
서블릿 필터는 서블릿에서 제공한다면, 스프링 인터셉터는 스프링 MVC 가 제공하는 기술이다. 둘 다 비슷하지만 적용되는 순서와 범위, 사용방법이 다르다.

스프링 인터셉터 흐름

  • 스프링 인터셉터는 디스패처 서블릿과 컨트롤러 사이에서 컨트롤러 호출 직전에 호출 된다.
  • 스프링 인터셉터는 스프링 MVC가 제공하는 기능이기 때문에 결국 디스패처 서블릿 이후에 등장하게 된다. 스프링 MVC의 시작점이 디스패처 서블릿이라고 생각해보면 이해가 될 것이다.
  • 스프링 인터셉터에도 URL 패턴을 적용할 수 있는데, 서블릿 URL 패턴과는 다르고, 매우 정밀하게 설정할 수 있다.

스프링 인터셉터 제한

인터셉터는 적절하지 않는 요청이라고 판단하면 거기서 바로 끝낸다. 이 부분도 로그인 여부 체크하기 좋은 방법이다.

스프링 인터셉터 체인

스프링 인터셉터 체인도 서블릿 필터와 같이 중간에 인터셉터를 자유롭게 추가할 수 있다. 필터와 다른 부분은 좀 더 편리하고, 더 정교한 다양한 기능을 제공한다.

인터셉터 인터페이스

  • 서블릿 필터의 경우 단순하게 doFilter() 하나만 제공된다.
  • 인터셉터는 컨트롤러 호출 전( preHandle ), 호출 후( postHandle ), 요청 완료 이후( afterCompletion )와 같이 단계적으로 잘 세분화 되어 있다.
  • 서블릿 필터의 경우 단순히 request , response 만 제공했지만, 인터셉터는 어떤 컨트롤러( handler )가 호출되는지 호출 정보도 받을 수 있다.
  • 어떤 modelAndView 가 반환되는지 응답 정보도 받을 수 있다.

스프링 인터셉터 호출 흐름

정상 흐름

  • preHandle : 컨트롤러 호출 전에 호출된다. (더 정확히는 핸들러 어댑터 호출 전에 호출된다.)

    • preHandle 의 응답값이 true 이면 다음으로 진행하고, false 이면 더는 진행하지 않는다.
    • false 인 경우 나머지 인터셉터는 물론이고, 핸들러 어댑터도 호출되지 않는다. 그림에서 1번에서 끝이나버린다.
  • postHandle : 컨트롤러 호출 후에 호출된다. (더 정확히는 핸들러 어댑터 호출 후에 호출된다.)

  • afterCompletion : 뷰가 렌더링 된 이후에 호출된다.

스프링 인터셉터 예외 상황

예외가 발생시

  • preHandle : 컨트롤러 호출 전에 호출된다.
  • postHandle : 컨트롤러에서 예외가 발생하면 postHandle 은 호출되지 않는다.
  • afterCompletion : afterCompletion 은 항상 호출된다. 이 경우 예외( ex )를 파라미터로 받아서 어떤 예외가 발생했는지 로그로 출력할 수 있다.

afterCompletion은 예외가 발생해도 호출된다.

  • 예외가 발생하면 postHandle() 는 호출되지 않으므로 예외와 무관하게 공통 처리를 하려면 afterCompletion() 을 사용해야 한다.
  • 예외가 발생하면 afterCompletion() 에 예외 정보( ex )를 포함해서 호출된다.

스프링 MVC 에 특화된 인터셉터 이기에 정말 필요한 상황에 필터를 써야하는 상황이 아니면 왠만하면 스프링 MVC 사용할 때는 인터셉터 사용을 추천한다.


스프링 인터셉터 - 요청 로그

LogInterceptor 신규 클래스 생성

요청 로그 인터셉터

HandlerMethod

핸들러 정보는 어떤 핸들러 매핑을 사용하는가에 따라 달라진다. 스프링을 사용하면 일반적으로 @Controller , @RequestMapping 을 활용한 핸들러 매핑을 사용하는데, 이 경우 핸들러 정보로 HandlerMethod 가 넘어온다.

ResourceHttpRequestHandler

@Controller 가 아니라 /resources/static 와 같은 정적 리소스가 호출 되는 경우 ResourceHttpRequestHandler 가 핸들러 정보로 넘어오기 때문에 타입에 따라서 처리가 필요하다.

postHandle, afterCompletion

종료 로그를 postHandle 이 아니라 afterCompletion 에서 실행한 이유는, 예외가 발생한 경우 postHandle 가 호출되지 않기 때문이다. afterCompletion 은 예외가 발생해도 호출 되는 것을 보장한다.

WebConfig - 인터셉터 등록

필터와 비교해보면 인터셉터는 addPathPatterns , excludePathPatterns 로 매우 정밀하게 URL 패턴을 지정할 수 있다.

이렇게 하면 스프링 인터셉터를 서블릿 필터 대체하여 사용할 수 있게 된다.


스프링 인터셉터 - 인증 체크

기존에 사용하던 서블릿 인증 체크를 스프링 인터셉터 인증 체크로 변경하는 작업을 하려고 한다.

서블릿 필터와 다르게 preHandle 만 구현하면 된다. 전 보다는 코드가 간결해진걸 확인 할 수 있다.

WebConfig - 인증 체크 변경

WebConfig 부분에 내용만 추가해주면 된다.

정리

서블릿 필터와 스프링 인터셉터는 웹과 관련된 공통 관심사를 해결하기 위한 기술이다.
서블릿 필터와 비교해서 스프링 인터셉터가 개발자 입장에서 훨씬 편리하다는 것을 코드로 이해했을 것이다. 특별한 문제가 없다면 인터셉터를 사용하는 것이 좋다.


ArgumentResolver 활용

ArgumentResolver 를 활용해서 로그인 회원을 조금 편리하게 찾아보자.

HomeController - 추가

@Login 애노테이션이 있으면 직접 만든 ArgumentResolver 가 동작해서 자동으로 세션에 있는 로그인 회원을 찾아주고, 만약 세션에 없다면 null 을 반환하도록 개발해보자.

@Login 애노테이션 생성

LoginMemberArgumentResolver 신규 클래스 생성

WebMvcConfigurer에 설정 추가

실행해보면, 결과는 동일하지만, 더 편리하게 로그인 회원 정보를 조회할 수 있다. 이렇게 ArgumentResolver 를 활용하면 공통 작업이 필요할 때 컨트롤러를 더욱 편리하게 사용할 수 있다.

profile
안녕하세요

0개의 댓글