스택큐힙리스트

Spring Boot 필터·인터셉터에서 발생한 예외 처리 방법 본문

개발

Spring Boot 필터·인터셉터에서 발생한 예외 처리 방법

스택큐힙리스트 2025. 7. 10. 17:55
반응형

Spring Boot 애플리케이션에서는 컨트롤러 진입 전 단계인 FilterInterceptor에서 인증·로깅·트래픽 제어 등의 처리를 하게 됩니다. 이 과정에서 예외가 발생할 수 있는데, 전통적인 @ControllerAdvice 전역 예외 처리 방식은 이 영역까지는 영향을 미치지 않습니다.

이번 포스팅에서는 필터와 인터셉터에서 예외가 발생했을 때 이를 어떻게 처리하고, 클라이언트에 일관된 에러 응답을 보낼 수 있는지에 대해 설명합니다.


✅ 왜 전역 예외 처리(@ControllerAdvice)로 잡히지 않을까?

@ControllerAdvice는 DispatcherServlet 이후 컨트롤러 진입 시점부터 발생한 예외만 처리합니다. 하지만 필터와 인터셉터는 그 이전 단계에서 실행되므로 @ControllerAdvice의 영향권 밖에 있습니다.


✅ Filter에서 예외 처리하기

Filter는 서블릿 단계에서 동작하기 때문에, 예외가 발생하면 직접 HTTP 응답을 조작해줘야 합니다.

@Component
public class JwtAuthFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        try {
            // JWT 토큰 검증 로직
            chain.doFilter(request, response);
        } catch (JwtException ex) {
            HttpServletResponse res = (HttpServletResponse) response;
            res.setStatus(HttpStatus.UNAUTHORIZED.value());
            res.setContentType("application/json");
            res.getWriter().write("{\"message\": \"토큰이 유효하지 않습니다.\"}");
        }
    }
}
  • 필터 내부에서 직접 응답 코드와 메시지를 설정해야 합니다.
  • ObjectMapper를 사용해 JSON 형태의 에러 응답을 만드는 것도 가능합니다.

✅ HandlerInterceptor에서 예외 처리하기

인터셉터는 비교적 DispatcherServlet에 가까운 레이어이지만, 여기서 발생한 예외도 @ControllerAdvice로는 처리되지 않습니다.

@Component
public class AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        if (인증실패조건) {
            throw new CustomAuthException("권한이 없습니다.");
        }
        return true;
    }
}

이 경우, 아래와 같은 방식으로 ExceptionResolver를 구현하여 처리할 수 있습니다.


✅ 필터/인터셉터 예외 공통 처리 – HandlerExceptionResolver 활용

@Component
public class CustomExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
                                         HttpServletResponse response,
                                         Object handler,
                                         Exception ex) {
        try {
            response.setStatus(HttpStatus.FORBIDDEN.value());
            response.setContentType("application/json");
            response.getWriter().write("{\"message\": \"" + ex.getMessage() + "\"}");
            response.getWriter().flush();
        } catch (IOException e) {
            // 로깅 처리
        }
        return new ModelAndView(); // 뷰 리졸빙 없이 직접 응답 처리
    }
}
  • Spring Boot가 예외 발생 시 HandlerExceptionResolver를 자동 호출
  • @ControllerAdvice와 달리, 필터/인터셉터 예외에도 대응 가능

✅ 실무 팁

  • 응답 포맷을 API 전체에서 통일하려면 ObjectMapper를 이용해 DTO 형태의 에러 메시지를 반환하도록 설계
  • ExceptionResolver는 여러 개 등록 가능하며, Ordered 인터페이스로 우선순위 설정 가능
  • Spring Security를 사용하는 경우 AuthenticationEntryPoint, AccessDeniedHandler를 활용해 예외 처리
반응형
Comments