서블릿 필터에 대해 알아보자
공통 관심사란?
애플리케이션에서 여러 로직이 공통적으로 신경 써야 하는 문제를 공통 관심사라고 한다.
예를 들어:
로그인하지 않은 비회원 유저가 상품 관리 페이지나 중요한 데이터에 접근하면 큰 문제가 발생할 수 있다.
이를 방지하려면 어떻게 해야 할까?
- 각 컨트롤러 메서드에 “로그인 여부 체크 로직”을 하나하나 작성해야 할 수도 있다.
- 하지만 이 방법은 복잡하고, 중복 코드가 많아지고, 유지보수가 어렵다.
- 만약 로그인 로직이 바뀌면 모든 코드를 수정해야 한다! 😱
공통 관심사를 해결하는 방법: 서블릿 필터
서블릿 필터는 이런 공통 관심사를 처리하기 위해 사용된다.
특히 웹 애플리케이션에서 HTTP 요청과 응답을 가로채 처리하는 데 유용하다.
서블릿 필터의 동작 흐름
- 서블릿 필터 흐름
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러 - 필터 제한
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러 (로그인 사용자)
HTTP 요청 -> WAS -> 필터(적절하지 않은 요청이라 판단 후 서블릿 호출 X) (비회원 사용자) - 필터 체인
HTTP 요청 -> WAS -> 필터1 -> 필터2 -> 필터3 -> 서블릿 -> 컨트롤러
1. Filter 구현하고 인증체크하기
public class CustomFilter implements Filter {
private static final String[] whitelist = {"/", "/members/singup", "/login", "/logout"};
@override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain){
//HttpServlet 기능이 더 많이 때문에 캐스팅을 해줘야한다!
HttpServletRequest httpRequest = (HttpServeltRequest) request;
String requestURI = httpRequest.getRequestURI(); //요청 URI 받기
HttpServletResponse httpResponse = (HttpServletResponse) response;
try {
if(isWhitelist(requestURI)) {
HttpSession session = httpRequest.getSession(false);
if(session == null || session.getAttribute(SessionConst.LOGIN_USER) == null) {
log.info("미인증 사용자 요청 {}", requestURI);
throw new RuntimeException("로그인 해주세요");
}
}
chain.doFilter(request, response);
} catch (Exception e) {
throw e;
} finally {
log.info("인증 체크 필터 종료");
}
}
//화이트 리스트의 경우 인증 체크 X
private boolean isWhitelist(String resultURI) {
return !PatternMatchUtils.simpleMatch(whitelist, requestURI);
}
}
코드 설명
- 화이트리스트 확인
if (!isWhitelist(requestURI)) :
방문자가 지나가려는 문(requestURI)이 “경비원이 신분증 확인 없이도 통과할 수 있는 문(화이트리스트)“인지 확인한다.
만약 화이트리스트에 포함되지 않은 문이라면, 신분증 확인 절차를 진행한다. - 세션 확인
HttpSession session = httpRequest.getSession(false) :
방문자가 "로그인해서 받은 신분증(세션)"을 가지고 있는지 확인한다.
getSession(false)는 이미 존재하는 세션이 없으면 새로운 세션을 만들지 않고 null을 반환한다. - 세션에 로그인 정보 확인
if(session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) :
신분증(세션)이 없거나, 신분증 안에 회원 정보가 없으면, "미인증 사용자 입니다! 통과할 수 없습니다"라고 요청을 막는다. - 요청 허용
위 조건을 모두 통과하면 요청을 처리하도록 다음 단계(컨트롤러)로 넘긴다.
주요 포인트
- chain.doFilter(request, response) : 이 부분이 가장 중요한데 다음 필터가 있으면 필터를 호출하고, 필터가 없으면 서블릿을 호출한다. 만약 이 로직을 호출하지 않으면 다음 단계로 진행되지 않는다.
- 화이트리스트 경로(로그인/회원가입)는 필터를 통과하지 않음.
- 비회원 사용자의 요청은 session을 확인하여 차단
2. Filter를 쓸 수 있게 등록을 해줘야 한다.
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean customFilter() {
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new CustomFilter()); //등록할 필터를 지정
filterRegistrationBean.setOrder(1); // chain 순서
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
마무리
서블릿 필터는 로그인 여부, 인증 로직, 공통 관심사를 깔끔하게 처리할 수 있다.
코드가 중복되지 않아 유지보수가 쉬워지고, 확장성도 높아진다.
'Back-End > Spring-MVC' 카테고리의 다른 글
| JWT(Json Web Token) (0) | 2025.01.04 |
|---|---|
| 스프링 글로벌 API 예외 처리와 @Valid 검증 예외 처리 (1) | 2024.12.31 |
| Cookie와 Session (0) | 2024.12.12 |
| HTTP 요청 / 응답 조합 상황별 사용 (0) | 2024.12.02 |
| HTTP 응답 데이터 (1) | 2024.12.02 |