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


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;
}
}
결과
- 로그인을 하지 않고 댓글을 작성할 경우 인증 절차가 수행됨

- 메인 코드에는 인증 확인을 거치는 코드를 지워도 수행되는 것을 확인 가능
@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 를 통해 로그인을 하지 않아도 진입 가능

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 호출
- 인증 코드를 추가하여 인증 절차 수행 가능

Share article