정리한 필터 내용 : https://www.notion.so/Filter-2aa555a1c11f80a28943d52ed761c900?source=copy_link

init() : 필터가 처음 등록될 때 호출 (서블릿 컨테이너 레벨)doFilter() : 실제 요청/응답을 가로채서 처리하는 핵심 메서드destroy() : 필터가 제거될 때 호출| 비교 항목 | Filter | GenericFilterBean | OncePerRequestFilter |
|---|---|---|---|
| 상속 관계 | 인터페이스 javax.servlet.Filter | extends Filter | extends GenericFilterBean |
| 관리 주체 | 서블릿 컨테이너 (Tomcat) | Spring IoC 컨테이너 | Spring IoC 컨테이너 |
| Bean LifeCycle | init() → destroy() | Spring Bean 생명주기(@PostConstruct, @PreDestroy 등) | Spring Bean 생명주기 동일 |
| DI (의존성 주입) | X 불가 | O 가능 | O 가능 |
| 등록 방식 | web.xml, FilterRegistrationBean | Spring @Component 또는 @Bean | Spring @Component 또는 @Bean |
| 역할 / 특징 | 가장 기본적인 필터, 단순 요청 처리 | 필터를 Spring Bean으로 다룰 때 필요한 기본 클래스 | “한 요청에 딱 한 번만 “ 실행되도록 보장 |
| 중복 실행 방지 | X 없음 (FORWARD / INCLUDE 시 여러번 실행됨) | X 없음 | O 있음 (Request 단계에서만 실행) |
| 대표 사용처 | 매우 단순한 커스텀 필터 | Spring 프로젝트에서 필터 만들 때 기본 베이스 | 인증, 권한 체크, 세션 체크, 로깅, CORS 등 |
| 장점 | 가장 기본 구조 | Spring DI, LifeCycle 활용 가능 | 동일 + 중복 호출 자동 방지 |
| 단점 | 스프링 기능 활용 불가 | 중복 호출 방지는 안 됨 | 가장 사용 목적이 명확해야 함 |
public class CustomFilter extends OncePerRequestFilter
//1. 커스텀 예외 처리 FORBIDDEN
CustomException exception = new CustomException(ExceptionCode.FORBIDDEN);
//2. 공용 응답 객체 생성
CommonResponse<String> result = new CommonResponse<>(exception.getExceptionCode().getStatus(), exception.getMessage());
//3. Controller에서 반환하는 ResponseEntity 사용
ResponseEntity<CommonResponse<String>> body = ResponseEntity.status(result.getStatus()).body(result);
//4. 응답 설정
response.setStatus(result.getCode());
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
//5, 객체를 String으로하는 라이브러리 사용 후 직렬화
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(result);
//6. 응답 작성
response.getWriter().write(json);
return;
//1. 공용 응답 객체 생성
CustomException exception = new CustomException(ExceptionCode.FORBIDDEN);
CommonResponse<String> result = new CommonResponse<>(exception.getExceptionCode().getStatus(), exception.getMessage());
//2. 응답 설정 application/json; charset=UTF-8 이런식으로 붙어 쓰라고 함
response.setStatus(result.getCode());
response.setContentType("application/json; charset=UTF-8");
//3. Json 변환 라이브러리
ObjectMapper objectMapper = new ObjectMapper();
//4. 직렬화 후 응답 작성
String json = objectMapper.writeValueAsString(result);
response.getWriter().write(json);
return;

@Slf4j
@Component
public class CustomFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { //요청과 응답을
//1. 세션 검사가 필요없는 경로 확인 false면 세션 검사 필요
boolean requiredSession = requiredSession(request);
//2. 세션 검사가 필요한 경우
if (requiredSession) {
//3. 세션 조회
HttpSession session = request.getSession(false);
if (session != null) {
//4. 세션에서 loginUser 속성을 꺼냄
SessionUser loginUser = (SessionUser) session.getAttribute("loginUser");
if (loginUser != null) {
log.info("CustomFilter doFilterInternal login id : {} email {}", loginUser.getId(), loginUser.getEmail());
//다음 요청으로 넘어갈 수 있게 사용하는 메서드
filterChain.doFilter(request, response);
return;
}
}
//5. 세션이 없거나 loginUser가 없으면 응답을 만들어서 줘야함
CustomException exception = new CustomException(ExceptionCode.FORBIDDEN);
CommonResponse<String> result = new CommonResponse<>(exception.getExceptionCode().getStatus(), exception.getMessage());
//6. 응답 설정 : HttpStatus, ContentType 및 인코딩
response.setStatus(result.getCode());
response.setContentType("application/json; charset=UTF-8");
//7. ObjectMapper 생성 후 object -> json으로 직렬화
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(result);
//8. 응답에 json 작성
response.getWriter().write(json);
return;
}
//다음 요청으로 넘어갈 수 있게 사용하는 메서드
filterChain.doFilter(request, response);
}
private boolean requiredSession(HttpServletRequest request) {
//요청 URI
String uri = request.getRequestURI();
String method = request.getMethod();
//인증 필요없는 곳
if (uri.startsWith("/signup") || uri.startsWith("/login") ||
("GET".equals(method))) return false;
return true;
}
}
request.getRequestURI() : 요청의 URI(컨텍스트 경로 제외한 경로)를 얻음 ex)/signup, /scheduelsrequest.getSession(false) : 세션을 새로 만들지 않고 기존 세션 조회response.setContentType("application/json; charset=UTF-8") : HTTP Response Body가 Json 형식 설정, 한글 깨짐 방지filterChain.doFilter(request, response) : 다음 요청으로 넘어갈 수 있게 사용하는 메서드//1. 인증 필요한 지 확인
if(requiredSession(request)) {
//인증 필요 로직
...
filterChain.doFilter(request, response);
return;
}
//2. 인증 필요한 URL -> 세션 검사
SessionUser user = session.getAttribute("loginUser");
filterChain.doFilter(request, response);
return;
//3. 인증 실패 -> JSON 에러 변환
response.getWriter().write(json);