개발/Spring

[Spring] 필터에서 발생한 예외는 어떻게 처리하는 게 좋을까?

서해쭈꾸미 2024. 5. 29. 23:03

JWT를 사용하여 인증 / 인가 처리를 해주는 필터를 만들고 있었다. 여기서 발생한 예외들을 처리해주어야하는데, 어떻게 처리하는 게 좋을지 고민해보았다.

 

 

1. GlobalExceptionHandler에서 처리해볼까 ?

Controller 및 Service에서 발생한 예외를 처리할 때 GlobalExceptionHandler를 만들어서 전역 처리해주었었다. 필터에서 발생한 예외도 여기서 처리하면 될까 ? 생각했었는데, 필터에서 발생하는 예외는 Controller를 들어오기 전에 발생되는 것이기 때문에 GlobalExceptionHandler에서는 처리할 수가 없다.

 

 

 

2. 필터 내부에서 예외처리 해주기

Spring Security를 사용하는 경우 ExceptionTranslationFilter와 같은 필터를 사용해서 발생한 예외를 처리해줄 수 있지만, 나는 Security를 사용하지 않고 JWT 인증 / 인가 필터를 직접 구현하고 있기 때문에 직접 예외 처리를 구현해야 겠다고 생각했다.

 

 

 

아래와 같이 필터내부에서 try catch문으로 발생한 예외를 잡아주고, (필터 내의 일부 코드이다.)

try {
        if (StringUtils.hasText(tokenValue)) { // 토큰이 존재하면 검증 시작

          // 토큰 검증
          if (!jwtUtil.validateToken(tokenValue)) {
              throw new IllegalArgumentException("토큰이 유효하지 않습니다.");
           }

          // 토큰에서 사용자 정보 가져오기
          Claims info = jwtUtil.getUserInfoFromToken(tokenValue);

          //회원 DB에 존재하는지 확인
          User user = userRepository.findByUsername(info.getSubject()).orElseThrow(() ->
                    new NullPointerException("회원가입 하지 않은 사용자입니다."));

          request.setAttribute("user", user); //인증완료된 User 객체 request에 담기
          chain.doFilter(request, response); // 다음 Filter 로 이동
          } else {
                 throw new IllegalArgumentException("토큰이 유효하지 않습니다.");
            }
       } catch (IllegalArgumentException | NullPointerException e) {
                FilterExceptionHandler.handleExceptionInFilter((HttpServletResponse) response, e);
          }

 

 

 

아래처럼 따로 예외를 처리해주는 클래스를 선언해서 예외처리해주었다.

@Slf4j(topic="AuthFilterException")
public class FilterExceptionHandler extends Exception {
   public static <T extends Exception> void handleExceptionInFilter(HttpServletResponse servletResponse, T e)throws IOException {
       log.error(e.getMessage());

       //서블릿 응답 UTF-8 인코딩
       servletResponse.setContentType("text/plain; charset=UTF-8");
       servletResponse.setCharacterEncoding("UTF-8");

       servletResponse.setStatus(400);
       servletResponse.getWriter().write("error :"+e.getMessage());
   }
}

 

인코딩은 클라이언트에 보내진 Reponse를 확인해보니 한글이 깨져서 나오길래 추가해주었다.