원래는 토비스프링 3.1에서도 말하지만 bean factory보다는 좀더 확장된 개념이 ApplicationContext이다라고 합니다
아무튼 어떤 기능에 대한 확장이니까 bean 객체들을 관리하는 IOC엔진이라고 생각하면 편합니다.
여기서 초보자 분들은
IOC는 역전 제어가 뭐지?라고 할수있습니다. 간단히 설명하면 IOC는 spring framework에 의존하는 방식이라 생각하면 좀 편합니다. 뭐 간단히 객체 생성같은거를 개발자가 아니라 framework가 대신해주는거죠! (말그대로 자동화!, 사람의 실수를 줄이는 거죠! 항상 개발자는 사람은 실수한다는 마음으로 개발해야 자동화를 하려고 노력하는것 같아요!)
.
이번엔 서블릿 컨테이너는 이전링크에서말했던 서블릿을 관리하는 컨테이너 겠죠
정의는 서블릿 컨테이너(Servlet Container)는 자바 웹 애플리케이션에서 중요한 역할을 하는 구성 요소입니다. 자바 서블릿을 실행하는 환경을 제공하며, 웹 서버와 함께 동작하여 HTTP 요청과 응답을 처리하는 역할입니다.
아래는 filter chain과 filter 인스턴스안에 DelegatingFilterProxy의 모습입니다.
DelegatingFilterProxy는 Bean Filter0 가 호출될때 ApplicationContext의 Bean Filter0에서 나타납니다. 아래 간단히 코드를 확인해보죠
여기서 스피링 빈에 등록된 필터는 lazily 하게 가져옵니다.(spring에서 lazy는 직접적 호출하기전까지는 생성및 초기화를 하지 않는다! 라고는걸로 있습니다. 즉 lazy 에 대한 개념을 알고가면 좋습니다.)
예를들어 DelegatingFilterProxy에서의 delegate 는 bean filter0의 instacne입니다.
여기서 delegate란?
일반적으로 객체가 특정 작업을 다른 객체에 위임하는 개념입니다. 즉 여기서 말하고자 하는것은 bean filter0가 DelegatingFilterProxy다 라고 생각하면 좋을듯합니다 ( 제가 틀렷다면 지적부탁드리겠습니다 제가 이해한건 이거입니다 )
여기서 2번 코드를 보면요
delegate.doFilter(request, response); //2
Spring bean에서 delgate 작업을 한다라고 합니다. 즉 DelegatingFilterProxy가 작동합니다
원문을 해석하면
마지막으로 DelegatingFilterProxy의 또 다른 장점은 Filter bean 인스턴스를 찾는 것을 지연시킬 수 있다는 것입니다. 이는 컨테이너가 시작되기 전에 Filter 인스턴스를 등록해야 하기 때문에 중요합니다. 그러나 Spring에서는 일반적으로 ContextLoaderListener를 사용하여 Spring Beans를 로드하는데, 이는 Filter 인스턴스가 등록되어야 할 시점 이후에야 완료됩니다.
말이 참 어렵죠.
먼저 ContextLoaderListener란?
주로 웹 기반의 Spring 애플리케이션에서 중요한 역할을 하며, 애플리케이션의 시작과 종료 시점에 각각 컨텍스트를 초기화하고 정리하는 역할을 합니다.( 즉 ApllicaitonContext를 초기화 및 종료 하는 역할 이라고 생각하면 편합니다. 일단 이것도 제가 생각한거라 틀릴수 잇습니다. 틀리면 지적부탁드립니다)
그렇다면
쉽게 설명하자면 spring에서 spring filter 인스턴스가 등록되어야 할 시점 이후에 ApplicationContext에서 spring beans을 불러오는겁니다. 근데 어째서 DelegatingFilterProxy는 필터 인스턴스를 늦게 로드 시킬까요?
(이유는 성능 최적화에 있다고하는데 . 당연한 얘기겟지만 모든 컴포너트를 즉시 로딩하면 상당한 양의 메모리를 차지하기 때문에 이런방식을 택한것같습니다. 이건 제추측입니다. 이것도 틀리면 지적부탁드립니다 보통 lazy한 경우가 다 성능 최적화여서 ㅠㅠ )
사실상 기존에 사용만 해봤지 실제 구조가 어떻게 굴러가는지에 대해서는 정확하게 공부하지 않았습니다.(반성중..사실 좀 바빳다는게 핑계... ㅎㅎ)
좋은 기회여서 일단 원서를 보면서 구조를 파악 해보려 합니다 ㅎㅎ
최대한 자세히 설명하거여서 쉬운 용어들 조차 설명을 할거라 내용이 조금 길어질수도 있습니다. 고수님들께서는 다른거 참조하셔도 됩니다. (저같은 초보를 위한 초보자들을 위해서... ㅎㅎ)
필터(filter)에 대해서
스프링 시큐리티의 서블릿 제공은 서블릿 필터에서 합니다!
여기서 서블릿이란? (모르는 분들을 위해서)
서블릿(Servlet)이란 동적 웹 페이지를 만들 때 사용되는 자바 기반의 웹 애플리케이션 프로그래밍 기술이다. 서블릿은 웹 요청과 응답의 흐름을 간단한 메서드 호출만으로 체계적으로 다룰 수 있게 해준다.(일단 spring mvc servlet에서는 DispatcherServlet 이어서 그건 아래에 설명하겠습니다.)
스프링 컨테이너는 스프링 프레임워크의 핵심 컴포넌트이다.
스프링 컨테이너는 자바 객체의 생명 주기를 관리하며, 생성된 자바 객체들에게 추가적인 기능을 제공한다.
스프링에서는 자바 객체를 빈(Bean)이라 한다.
즉, 스프링 컨테이너는 내부에 존재하는 빈의 생명주기를 관리(빈의 생성, 관리, 제거 등)하며, 생성된 빈에게 추가적인 기능을 제공하는 것이다.
스프링 컨테이너는 XML, 어노테이션 기반의 자바 설정 클래스로 만들 수 있다.
스프링 부트(Spring Boot)를 사용하기 이전에는 xml을 통해 직접적으로 설정해 주어야 했지만, 스프링 부트가 등장하면서 대부분 사용하지 않게 되었다.
출처: https://ittrue.tistory.com/220 [IT is True:티스토리]
블로그 글을 빌리자면 스프링 자바 객체를 자동적으로 생명주기를 관리해주는곳이 컨테이너입니다.
디스패처 서블릿의 dispatch는 "보내다"라는 뜻을 가지고 있습니다. 그리고 이러한 단어를 포함하는 디스패처 서블릿은 HTTP 프로토콜로 들어오는 모든 요청을 가장 먼저 받아 적합한 컨트롤러에 위임해주는 프론트 컨트롤러(Front Controller)라고 정의할 수 있습니다.
이것을 보다 자세히 설명하자면, 클라이언트로부터 어떠한 요청이 오면 Tomcat(톰캣)과 같은 서블릿 컨테이너가 요청을 받게 됩니다. 그리고 이 모든 요청을 프론트 컨트롤러인 디스패처 서블릿이 가장 먼저 받게 됩니다. 그러면 디스패처 서블릿은 공통적인 작업을 먼저 처리한 후에 해당 요청을 처리해야 하는 컨트롤러를 찾아서 작업을 위임합니다.
여기서 Front Controller(프론트 컨트롤러)라는 용어가 사용되는데, Front Controller는 주로 서블릿 컨테이너의 제일 앞에서 서버로 들어오는 클라이언트의 모든 요청을 받아서 처리해주는 컨트롤러로써, MVC 구조에서 함께 사용되는 디자인 패턴입니다.
출처: https://mangkyu.tistory.com/18 [MangKyu's Diary:티스토리]
말그대로 http 요청이 오면 가장 먼저 받는 위치에 존재하는 컨트롤러라고 생각하시면 편합니다.
당연히 아시겟지만 하나의 서블릿은 HttpServletRequest 및 HttpServletResponse를 처리할 수 있습니다.
하지만!! 하나 이상의 filter는 아래 다음과 같은 목적으로 이용할수 있습니다.
DownStream Filter 인스턴스 또는 서블릿이 호출되는 것을 방지합니다. 이 경우 필터는 일반적으로 HttpServletResponse를 작성합니다.
DownStream Filter 와 서블릿이 사용하는 HttpServletRequest나 HttpServletResponse를 수정합니다
DownStream Filter란?(저도 몰랐네요 ..)
말그대로 특정 필터 이후에 위치하는 필터들을DownStream Filter라고 합니다.
결국 여기서 말하자고 하는것은요.
원문을보면
The power of the Filter comes from the FilterChain that is passed into it.
저도 이해한느낌이 filter의 강력한 힘은 filterchain을 통함으로라는건데 filter의 강력한점이 filterchain덕분이다 라는뜻 같네요. (혹시나 저도 이부분좀 이해가 안가서 이런느낌인가 합니다.)
간단히 filter chain의 코드를 보겟습니다.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// do something before the rest of the application
chain.doFilter(request, response); // invoke the rest of the application
// do something after the rest of the application
}
오늘은 여기까지하고 내일은 DelegatingFilterProxy에 대해서 알아보겠습니다.