WebServer VS WAS(Web Application Server)
웹서버
정적인 html, css, 파일 등의 정적 컨텐츠를 사용자 요청에 따라 보냄
WAS
웹서버와 웹 컨테이너를 포함하거나 웹 컨테이너를 자체를 뜻하고 사용자가 동적 컨텐츠 이용시에는 웹서버는 웹 컨테이너에 요청해 응답을 보내준다.
Servlet
웹서버를 거쳐 넘어온 요청, 응답을 자바 프로그램과 소통할 수 있게 웹 서버와 소켓을 만들어 통신을 지원하는 자바 API
동적 웹 페이지(요청에 따른 비즈니스 로직 적용한 응답)을 만들 때 사용
Servlet의 생명주기
- 서블렛 클래스 로딩 및 인스턴스화 : 요청이 오면 Servlet 클래스가 로딩되어 요청에 대한 Servlet 객체 생성
- 초기화 : init() 메소드 호출로 Servlet 초기화, 디폴트로 초기 요청에만 실행
- 서비스 : service() 메소드 호출로 Servlet에게 요청 처리
- 종료 : destroy() 메소드 호출로 Servlet 제거, GC 진행, 디폴트로 서버 종료시에만 실행
WAS 웹 요청 흐름
- 클라이언트가 URL로 Web Server에 접근
- Web Server는 동적 웹 요청을 확인하면 Servlet Container에게 요청 전달
- 요청받은 Servlet Container는 HttpServeltRequest, HttpServeltResponse 객체 생성
- URL에 해당하는 서블렛 조회
- 해당 서블렛이 초기 요청을 처리한적 없다면 Servlet Container에 서블렛 객체 생성 및 init() 메소드 호출
- 해당 요청을 처리할 스레드를 스레드풀에서 빌려오거나, 스레드 생성
- 스레드를 확보했으면 서블렛 객체의 service() 메소드 호출
- 메소드 실행 시 HttpServletRequest로 부터 정보를 얻고 HttpServletResponse에 응답 정보 담아 Serlvet Container에게 전달
- Serlvet Container는 HttpServletResponse 객체를 HTTP Response로 전환해 웹서버로 보냄
- Serlvet Container는 전환 응답 후에 HttpServletRequest, HttpServletResponse 객체 소멸, 스레드 반환
Serlvet Contianer의 역할
웹서버와 통신지원
서블렛과 웹서버의 통신을 추상화 된 API를 제공해서 개발자가 복잡한 웹 연결 과정을 생략할 수 있게 한다.
서블렛의 생명주기 관리
스프링 컨테이너처럼 서블렛의 주기를 관리
멀티쓰레드 지원 및 관리
서블렛 컨테이너는 요청이 올 때마다 자바 쓰레드 생성 및 응답 후 소멸
쓰레드의 생성 처리비용이 높기 때문에 쓰레드풀에서 쓰레드를 빌려와서 사용하고 다시 반납하는 것을 서버가 관리
스프링의 Dispatcher Servlet
서블렛 컨테이너에서 여러 서블렛을 등록하고 요청에 따른 서블렛을 수행 및 반환하는 것을 FrontController 패턴을 적용한 스프링의 디스패쳐 서블렛으로 위임하고 디스패쳐 서블렛은 요청에 따라 적절한 핸들러(컨트롤러)로 요청 위임 후 반환을 맡음
디스패쳐 서블렛에 위임한 후의 doService() 에 대한 내용은 포스트 참조
Root ApplicationContext, Servlet ApplicationContext
뜬금없이 스프링 IoC 컨테이너가 왜 나오나 할 수도 있지만 스프링부트가 제공해주는 기능 때문에 애매하게 알고 있던 부분이다.
김영한님의 스프링 로드맵을 따라가면서 스프링부트를 사용하면 루트 애플리케이션 클래스를 포함한 루트 패키지 아래로는 ComponentScan을 통해 @Component 및 포함하는 어노테이션을 가지고 있는 클래스들을 스프링 컨테이너에 띄워주고 @Autowired를 통해 의존성을 주입해준다고 알고 있다.
DispatcherServlet의 doService, doDispatch이 메인이지만 요청에 따른 적절한 핸들러에게 위임하기 전에, 핸들러들을 생성하는 부분도 DispatcherServlet이 담당한다고 한다.
여기에 스프링 웹 MVC가 추가되면 Servlet에 대한 추가적인 servlet application context가 추가된다.
Servlet WebApplication Context
DispatcherServlet과 묶이는 interceptor, viewResolver, Controller 같이 웹에서 사용되는 것들은 최초 요청이 들어올 때 서블렛 컨테이너가 초기화시에 DispatcherServlet에 의해 servlet application context에 올린다.
RootWebApplication Context
하지만 웹과 묶이는 부분이 아닌 DB, Service, Repository 부분은 요청과는 상관없이 미리 띄워두고 응답 후에도 유지를 하는편이 좋기 때문에 요청이 들어오기전에 ContextLoaderListener에 의해 root application context 생성하고 그 위에 올린다.
root context가 먼저 생성되기에 root context는 servlet context를 참조할 수 없지만 그 역은 가능하다.
Service, Repository, DB 등 웹과 관련 없는 부분은 ContextLoaderListener에 의해 최초 main 메소드 호출 시 메모리에 올린다.
웹 요청이 들어오면 DispatcherServlet의 doService 전에 웹과 관련된 부분을 메모리에 올린다.
// 쓰레드, 멀티쓰레드에 대한 내용 공부 후 추가하기
참고
https://gmlwjd9405.github.io/2018/10/27/webserver-vs-was.html
https://chonahyeon.github.io/posts/ServletContainer/