[스프링부트] 24. Blog v2 : Intercept

문정준's avatar
Apr 11, 2025
[스프링부트] 24. Blog v2 : Intercept

1. Filtering & Intercept

✏️
필터링 & Intercept
  • Client의 URI 요청에 따라 주소 파싱을 통해 인증 등의 절차를 사전에 진행 후 Process 진행
  • Filter : Tomcat과 DS 사이에서 필터링
    • 빠른 처리 가능, Spring 밖에서 작동하므로 Spring 내부 기능 사용 불가
    • 서버 내 모든 요청을 처리 가능
  • Interceptor : DS와 동등한 위치에서 인증, 예외 처리 등의 catch 기능 활용
    • Spring 내부에서 작동하므로 Spring에서 제공하는 편의 기능 이용 가능
    • Spring 내부로 접근하는 요청만 처리 가능 (Controller 등)
  • 🔐 보안, CORS, 로깅, 인코딩 등 모든 요청에 대해 작동시켜야 하는 기능 → Filter 사용
  • 🧭 인증, 권한 체크, 사용자 컨텍스트 주입 등 컨트롤러 앞뒤 작업Interceptor 사용
notion image
notion image
 

2. Interceptor 처리

  • WebMvcConfigurer 인터페이스 활용 : addInterceptor
    • 어느 링크의 요청을 받았을 때에 요청을 수행할 지, 수행하지 않을 지 결정 가능
    • board 내부 기능은 인증이 필요한 반면, 상세보기와 리스트의 경우 인증이 필요 없음
      • .excludePathPatterns에 정규 표현식을 추가하여 주소 내 특정 패턴은 제외 가능
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/user/**") .addPathPatterns("/board/**") .addPathPatterns("/love/**") .addPathPatterns("/reply/**") .addPathPatterns("/api/**") // Board 상세보기 : session 인증 없이 볼 수 있어야 함 - 글의 수정/삭제와 주소가 겹침 >> 정규 표현식 // 정규 표현식 : ChatGPT에 검색!! .excludePathPatterns("/board/{id:\\d+}"); } }
 
  • LoginInterceptor
    • 클라이언트의 로그인 여부를 확인할 수 있는 HandlerInterceptor
    • Spring 기능을 이용 가능하므로 예외 처리 또한 사용 가능 (GlobalExceptionHandler)
    • Filter를 사용할 경우, Spring 기능 이용이 불가하므로 주석 부분까지 추가 작성 필요
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; } }
 

결과

  • 로그인을 하지 않고 댓글을 작성할 경우 인증 절차가 수행됨
notion image
  • 메인 코드에는 인증 확인을 거치는 코드를 지워도 수행되는 것을 확인 가능
@PostMapping("/reply/save") public String save(ReplyRequest.SaveDTO saveDTO, HttpSession session) { User sessionUser = (User) session.getAttribute("sessionUser"); replyService.댓글저장(saveDTO, sessionUser); return "redirect:/board/"+saveDTO.getBoardId(); }
  • 다만, 상세보기의 경우 excludePathPatterns 를 통해 로그인을 하지 않아도 진입 가능
notion image

Test

  • 경로 설정 후, preHandle 동작 확인을 위한 sout 처리
package shop.mtcoding.blog._core.interceptor; import com.fasterxml.jackson.databind.ObjectMapper; 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._core.util.Resp; import shop.mtcoding.blog._core.util.Script; import shop.mtcoding.blog.user.User; import java.io.PrintWriter; public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("--------------------------------"); System.out.println("preHandle 호출됨"); System.out.println("--------------------------------"); return true; } }
 
  • 로그인한 후 글을 수정하려고 수정 버튼을 누를 경우 콘솔에 preHandle 호출
    • 인증 코드를 추가하여 인증 절차 수행 가능
notion image
 
Share article

sxias