[SB] 14. Interceptor

최재원's avatar
May 07, 2025
[SB] 14. Interceptor
notion image
dispatcher 와 같은 공간에 있는 컴포넌트다
기능은
  • dispatcher의 invoke() 앞, 뒤에서 실행할 수 있다
  • invoke() 앞에서 실행되면 컨트롤러의 메서드를 호출 하기 전 어떠한 기능을 실행 할 수 있다는 것
  • invoke() 뒤에서 실행되면 컨트롤러의 응답이 끝난 뒤에 어떠한 기능을 실행 할 수 있다는 것
  • 인터셉터에서 예외를 터트리면 dispatcher가 그 에러를 잡아서 처리 할 수 있다

Interceptor란

HTTP 요청과 응답의 흐름을 가로채어, 컨트롤러 실행 전후에 개발자가 원하는 공통 작업(인증, 권한 체크, 로깅 등)을 처리할 수 있도록 해주는 스프링 MVC의 핵심 컴포넌트입니다. 컨트롤러의 로직을 수정하지 않고도, 요청과 응답의 흐름에 개입해 전처리/후처리/완료 후 작업을 추가할 수 있습니다

주요 특징

  • 공통 관심사 처리: 로그인 체크, 권한 검증, 로깅 등 여러 컨트롤러에서 반복적으로 처리해야 하는 작업을 한 곳에 모아 효율적으로 관리할 수 있습니다.
  • 요청/응답 가로채기: 특정 URI 패턴에 대한 요청을 가로채 처리할 수 있으며, 컨트롤러 실행 전후, 뷰 렌더링 이후 등 다양한 시점에 개입이 가능합니다.
  • 정밀한 URL 패턴 지정: 서블릿 필터보다 더 세밀하게 URL 패턴을 지정해 적용할 수 있습니다

✅ 스프링 인터셉터의 위치

인터셉터는 다음 위치에서 동작합니다:
[클라이언트][DispatcherServlet][인터셉터 (preHandle)][컨트롤러][인터셉터 (postHandle)][뷰 렌더링][인터셉터 (afterCompletion)][응답 반환]

✅ 스프링 인터셉터의 주요 특징

항목
설명
동작 위치
DispatcherServlet과 Controller 사이
사용 목적
인증/인가 체크, 로깅, 공통 설정 등
구성 방법
HandlerInterceptor 인터페이스 구현 후 등록
요청 제어 가능
preHandle()에서 false를 반환하면 요청 중단 가능

💡 인터셉터 주요 사용 예

  • 로그인 세션 검사
  • 사용자 권한 검사
  • 요청 처리 시간 측정
  • 공통 로그 처리
  • API 토큰 인증

Interceptor vs Filter

인터셉터는 db에 접근해서 더 많은 정보를 확인하고 처리할 수 있다

  • 필터는 주어진 정보만 확인 가능하다.
  • 세션을 사용한다면 둘의 차이를 느끼기 힘들다
    • 세션에 모든 정보를 넣어두면 필터에서도 읽을 수 있기 때문
  • 토큰을 사용한다면 차이를 느낄 수 있다
    • 필터에서는 토큰 정보로 db 조회가 불가능하다
    • 인터셉터는 조회가 가능하다

🔸 예시 2: 특정 URI마다 권한 체크 (예: 관리자만 접근 가능)

// preHandle if (request.getRequestURI().startsWith("/admin")) { if (!user.hasRole("ADMIN")) { response.sendRedirect("/no-access"); return false; } }
  • URL 패턴에 따라 컨트롤러 실행을 사전 제어
  • Controller 레벨의 접근 제한을 일관되게 적용 가능

✅ 요약 비교

용도
필터 (Filter)
인터셉터 (Interceptor)
로그인 여부만 판단
✅ 적절
가능하지만 과함
로그인 + 유저 로딩 + 권한 체크
❌ 복잡해짐
✅ 적절
요청/응답 전후 전역 처리
✅ 적절
✅ 가능
컨트롤러 내부 흐름과 밀접한 제어
❌ 불가
✅ 강력
뷰 렌더링 제어
❌ 불가
✅ 가능
Spring MVC 연동
❌ 모름
✅ 완벽히 통합됨

🔚 결론

  • 간단한 인증/토큰 체크는 Filter로 충분
  • 컨트롤러 흐름 제어, 세션/권한/공통 Model 처리 등은 Interceptor가 훨씬 적합
    • → 특히 Spring MVC 기반 프로젝트라면 인터셉터는 꼭 써야 하는 도구입니다.
 

12. 유저인증 인터셉터

notion image

☕_core/config/WebMvcConfig

package shop.mtcoding.blog._core.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import shop.mtcoding.blog._core.interceptor.LoginInterceptor; @Configuration // Ioc 컨테이너에 설정파일을 등록 public class WebMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/user/**") .addPathPatterns("/board/**") .excludePathPatterns("/board/{id:\\d+}") .addPathPatterns("/love/**") .addPathPatterns("/reply/**") .addPathPatterns("/api/**"); } }
  • WebMvcConfigurer → 스프링 MVC를 확장/커스터마이징할 수 있는 인터페이스(설정 클래스)
  • @Configuration → Ioc 컨테이너에 등록 하는 방법
  • addInterceptors → 스프링에 인터셉터를 등록할 때 사용하는 메서드
  • InterceptorRegistry registry → 인터셉터 등록 도구
  • addPathPatterns → 해당 주소로 요청이 들어오면 인터셉트 처리를 한다
  • excludePathPatterns → 해동 주소는 인터셉트 처리를 제외한다

☕_core/interceptor/LoginInterceptor

package shop.mtcoding.blog._core.interceptor; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import org.springframework.web.servlet.HandlerInterceptor; import shop.mtcoding.blog._core.error.ex.Exception401; import shop.mtcoding.blog._core.error.ex.ExceptionApi401; import shop.mtcoding.blog.user.User; public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String uri = request.getRequestURI(); System.out.println("uri: " + uri); HttpSession session = request.getSession(); User sessionUser = (User) session.getAttribute("sessionUser"); if (sessionUser == null) { if (uri.contains("/api")) { throw new ExceptionApi401("인증이 필요합니다"); // response.setStatus(401); // response.setHeader("Content-Type", "application/json"); // PrintWriter out = response.getWriter(); // Resp<?> resp = Resp.fail(401, "인증이 필요합니다"); // ObjectMapper mapper = new ObjectMapper(); // String responseBody = mapper.writeValueAsString(resp); // out.println(responseBody); // return false; } else { throw new Exception401("인증이 필요합니다"); // response.setStatus(401); // response.setHeader("Content-Type", "text/html"); // PrintWriter out = response.getWriter(); // out.println(Script.href("인증이 필요합니다", "/login-form")); // return false; } } return true; } }
  • HandlerInterceptor → 컨트롤러가 실행되기 전/후/완료 후에 동작할 수 있는 인터셉터(Interceptor) 기능을 제공하는 인터페이스
  • preHandle → invoke() 앞에서 처리하는 핸들러
  • return true → true 리턴하면 invoke()가 실행 된다. false 면 요청 처리 바로 종료

Share article

jjack1