개요
로그인이 안 된 사용자는 로그인하라고 가게하고 로그인이 된 사용자만 우리 페이지를 보여주고 싶다
이런 건 모든 컨트롤러의 공통으로 해야 하는 과제다
컨트롤러 하나 하나 하는게 아니라 요청이 오면 요청을 검사하는 공통으로 해야 하는 과제가 생겼다
요구사항
- 지금 이 사용자가 로그인 됐는지 확인
- 로그인이 안됐으면 리다이렉트 페이지로
- 로그인이 됐으면 계속 이용하게 하자
스프링 필터

필터의 위치
HTTP 요청 -> WAS(response,request객체) -> 필터 -> Dispatcher서블릿 -> 컨트롤러
스프링의 필터의 위치는 ServletContainer 안에 존재한다. 그리고 그중에서도 DispatcherServlet 앞단에 존재한다
그래서 필터를 이용해 모든 고객의 요청 로그를 남길 수도 있다
참고
HttpServletReqeust, HttpServletResponse 는 인터페이스야 이 인터페이스를 보고 WAS(Tomcat)가 구현객체인 response, request를 만들어줘 이 안에 무수한 많은 기능들이 있음을 이제까지 봤음. getCookie , getSession, getHeader.. 등등 이렇게 만든 그래서 Tomcat이 이래서 필요한 거군 아!!!
서블릿 필터 인터페이스
인터페이스는 는 다음과 같이 생겼다
public interface Filter {
public default void init(FilterConfig filterConfig) throws ServletException {}
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain)
throws IOException, ServletException;
public default void destroy() {}
}
메서드는 총 3개가 있는데 진짜로 구현 해야하는 메소드는 doFilter다
(왜냐면 default 가 붙여져 있어서 기본으로 구현되어 있다)
각 Method의 역할은 다음과 같다
- init(): 필터 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출된다
- doFilter(): 고객의 요청이 올 때마다 해당 메서드가 호출된다. 필터의 로직을 구현하면 된다.
- destroy(): 필터 종료 메서드, 서블릿 컨테이너가 종료될 때 호출된다.
우리만의 필터를 만들려면 이 필터 인터페이스를 구현해야 한다
@Slf4j
public class LogFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("log filter init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("log filter doFilter");
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
String uuid = UUID.randomUUID().toString();
try {
log.info("REQUEST [{}][{}]",uuid,requestURI);
chain.doFilter(request,response);
} catch (Exception e) {
throw e;
}finally {
log.info("RESPONSE[{}][{}]",uuid,requestURI);
}
}
@Override
public void destroy() {
log.info("log filter destory");
}
}
doFilter에서 우리가 구현해야 하는 Fitler 로직을 구현해 주면 된다
여기서 중요한 점은
chain.doFilter(request,response);
이걸 꼭 해야 한다!!!!!!!!!!
그래야 스프링이 제공하는 다음 필터로 넘어가서 컨트롤러까지 쭉 요청이 갈 수 있다 이걸 안 하면 여기서 그냥 막히고 끝난다...
다시 한번 말하는데 꼭 doFilter를 해야 한다
필터를 등록하자
@Configuration
public class WebConfig implements WebMvcConfigure {
@Bean
public FilterRegistrationBean logFilter() {
FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
filterFilterRegistrationBean.setFilter(new LogFilter());
filterFilterRegistrationBean.setOrder(1);
filterFilterRegistrationBean.addUrlPatterns("/*");
return filterFilterRegistrationBean;
}
}
필터를 등록할 때 FilterRegistrationBean을 반환하는 빈을 설정해야 한다
오버라이드를 제공을 안 해서 조금 번거롭다
해당 빈에 우리의 필터를 등록하고(setFilter)
우선순위를 설정한 다음 (setOrder())
필터를 통과할 Url을 설정한다 (addUrlPatters)
스프링 인터셉터

스프링 인터셉터도 공통 관심 사항을 효과적으로 해결할 수 있는 기능인데 서블릿 필터는 서블릿이 제공하는 기능이고 스프링 인터셉터는 스프링 MVC 가 제공하는 기술이다
흐름
HTTP요청 -> WAS -> 서블릿 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러
스프링 인터셉터는 Dispatcher 서블릿과 컨트롤러를 호출 직전에 호출한다
스프링 인터셉터도 URL 패턴을 적용할 수 있는데 서블릿 URL 패턴과는 다르게 매우 정밀하게 설정 가능하다
이렇게 생각하자
- 서블릿 필터 들어가기 전에 → 서블릿 필터
- 서블릿 필터 나오고 난 후 → 스프링 인터셉터
인터페이스
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {}
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 {}
- preHandle
→ 응답이 true 면 다음 인터셉터 or Controller 호출 → 응답이 false 면 더 이상 진행 X
→ 핸들러 어댑터 호출 전에 호출됨 - postHandle
→ 컨트롤러 호출 후 - afterCompletion
→ 뷰가 렌더링 된 이후에 호출
인터셉터의 예외
인터셉터의 예외 상황

예외가 발생 시
- preHandle: 컨트롤러 호출 전에 호출된다.
- postHandle :컨트롤러에서 예외가 발생하면 postHandle 은 호출되지 않는다.
- afterCompletion: afterCompletion 은 항상 호출된다. 이 경우 예외( ex)를 파라미터로 받아서 어떤 예외가 발생했는지 로그로 출력할 수 있다
afterCompletion은 예외가 발생해도 호출된다.
- 예외가 발생하면 postHandle()는 호출되지 않으므로 예외와 무관하게 공통 처리를 하려면 afterCompletion()을 사용해야 한다.
- 예외가 발생하면 afterCompletion()에 예외정보(ex)를 포함해서 호출된다.
서블릿 필터를 사용할 특수한 상황이 아니라면 인터셉터를 사용하자
요구사항에 맞춰 인터셉터를 구성해 보면
@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();
if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {
log.info("미인증 사용자 요청 입니다");
//로그인으로 리다이렉트
response.sendRedirect("/login?redirectURL="+requestURI);
return false;
}
return true;
}
}
이렇게 간단하게 구현할 수 있다
preHandle에서 컨트롤러에 들어가기 전에 Session을 꺼내보기 시작한다
만일 Session이 비어있다면 아직 로그인이 되지 않은 상황임으로 redirect를 진행한다
참고
Filter를 살펴보면 어디서 많이 본듯한 것 같다
맞다! 스프링 Security가 이 필터로 구성되어 있다
인터셉터의 등록
public class WebConfig implements WebMvcConfigure{
@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("/", "/members/add", "login", "/logout",
"/css/**", "/*.ico", "/error");
}
인터셉터는 Filter와는 다르게 Override를 제공한다
registry에서 인터셉터를 등록을 하고 (addInterceptor),
우선순위 설정 (order)과
검증 url 설정(addPaterrns("/**") ,
그리고 excludePathPattern을 통해 인터셉터에서 제외할 URL을 구성하면 된다

'🌿 스프링 > 스프링 MVC 2편' 카테고리의 다른 글
| API 예외처리 (0) | 2026.02.15 |
|---|---|
| 서블릿 예외 처리와 오류 페이지 (0) | 2026.02.15 |
| 로그인 처리- 쿠키,세션 (0) | 2026.02.14 |
| Validation (0) | 2026.02.14 |
| 메시지 , 국제화 기능 (0) | 2026.02.14 |