만약, 웹 브라우저 페이지 중 로그인한 회원만 이용할 수 있는 기능들이 있을때, 어떻게 개발을 해야할까? 아마, 로그인한 회원 정보가 필요한 로직들에 공통적으로 로그인 여부를 확인하는 코드(공통관심사)를 다 작성을 해야할 것이다. 하지만 이는 중복되는 코드도 많고 유지보수적으로 애로사항이 매우 크다.
이렇게 애플리케이션 여러 로직에서 공통으로 관심이 있는 있는 것을 공통 관심사(cross-cutting concern)라고 한다. 이러한 공통 관심사를 해결하는 방법은 다음과 같다.
- 스프링 AOP
- 필터, 인터셉터
웹과 관련된 공통 관심사를 처리할 때는 HTTP의 헤더나 URL의 정보들이 필요하기 때문에 필터, 인터셉터를 활용하여 해결하는 것이 좋다. 서블릿 필터나 스프링 인터셉터는 HttpServletRequest 를 제공하기 때문이다.
필터의 특성
필터는 요청, 응답의 최전방에 존재한다. 그래서 WAS에서 관리한다.
- 주로, 들어온 데이터를 다른 데이터로 변환시켜서 안쪽으로 전송하는 역할
- 들어온 데이터에 대해서 모든 내용을 기록하는 역할(로그 시스템)
필터 흐름
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러
- 필터를 적용하면 필터가 호출된 다음에 서블릿(DispatcherServlet)이 호출된다.
- 필터는 특정 URL 패턴에 적용할 수 있다.
- 만약, ' /* '이라고 하면 모든 요청에 필터가 적용된다.
필터 제한
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러 // ex) 로그인 사용자
HTTP 요청 -> WAS -> 필터(적절하지 않은 요청이라 판단, 서블릿 호출X) // ex) 비 로그인 사용자
- 필터에 적절하지 요청이라고 판단되면 거기에서 끝낼 수 있다. 따라서, 로그인 여부와 같은 기능들에서 유용하게 적용할 수 있다.
필터 체인
HTTP 요청 -> WAS -> 필터1 -> 필터2 -> 필터3 -> 서블릿 -> 컨트롤러
- 필터는 체인으로 구성되는데, 여러 개의 필터를 단계적으로 설정하여 필터를 자유롭게 구성할 수 있다.
- 예를 들어, 로그를 남기는 필터를 적용한 후, 로그인 여부를 체크하는 필터를 만들 수 있다.
필터 인터페이스
public interface Filter {
//필터 초기화 메서드
public default void init(FilterConfig filterConfig) throws ServletException
{}
//필터의 로직을 구현
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException{}
//필터 종료 메서드
public default void destroy() {}
}
- init(): 필터 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출된다.
- doFilter(): 고객의 요청이 올 때 마다 해당 메서드가 호출된다. 필터의 로직을 구현하면 된다.
- destroy(): 필터 종료 메서드, 서블릿 컨테이너가 종료될 때 호출된다.
인터셉터
필터와 달리 DispatcherServlet 안 쪽에 위치하여 컨트롤러로 넘어가기 직전에 기능을 수행한다. 따라서, Spring Bean으로 스프링에서 관리한다.
- Handler Mapping을 통해 실행할 컨트롤러가 정해졌기 때문에, 해당 컨트롤러가 가지고 있는 어노테이션을 찾아서 작업을 처리하는 역할
- 헤더에 있는 내용을 보고 권한을 검사하는 역할 등
- 주로, 인증에 관한 역할 수행을 많이 한다.
- 정상적인 데이터 검증
- 어떠한 권한을 가지고 있는지 등
'Spring > SpringMVC' 카테고리의 다른 글
스프링 부트 - 오류페이지 처리 (0) | 2024.02.19 |
---|---|
서블릿 예외처리 (0) | 2024.02.15 |
쿠키, 세션을 활용한 로그인, 로그아웃 (0) | 2024.02.04 |
검증 - Bean Validation (0) | 2024.01.22 |
검증 - Validation 2 (1) | 2024.01.21 |