WAS 서블릿 컨테이너 파헤치기

devdo·2022년 1월 3일
3

JSP/Servelt

목록 보기
2/2

WAS의 정체

자, was의 정체를 알아보자.
WAS는 web server + 컨테이너라고 볼 수 있다.

응? 컨테이너? 이게 뭘까?

was의 정체를 알려면, 서블릿 컨테이너라는 개념을 잘 알아야 한다!

(정확하게는, 서블릿 컨테이너 = Servlet + JSP + EJB 컨테이너)

서블릿 컨테이너는 개발자가 웹서버와 통신하기 위하여 소켓을 생성하고, 특정 포트에 리스팅하고, 스트림을 생성하는 등의 복잡한 일들을 할 필요가 없게 해주는, 자바 웹 어플리케이션 동적 페이지를 만들어 주는 기술이다.(원래 소켓, 스트림 등으로 통신하는 것이었음..)


💡 Spring과 같이 넓게 보자!
WAS의 대표적인 예시가 Tomcat 이다.

이 Tomcat은 Java로 코드로 구현되어 있는데, Servlet이라는 최상위 인터페이스를 참조하고 있고, Tomcat에게 Reqeust가 오면, Tomcat이 추가적으로 내장하고 있는 WS(웹서버)에게 정적인 페이지를 요청하고, 추가적으로 동적데이터가 필요한 경우, Servlet에게 책임을 떠넘긴다!

그럼 Spring 어플리케이션인 경우 Dispatcher Servlet은 이 Servelt을 구현하는 클래스로, 작동flow는 다음과 같다.

WS에게 정적인 페이지 요청 OR 동적인 페이지 필요한 경우 WAS에게 요청

1) WAS 는 요청의 처리 책임을 Servelt에게 위임
2) Spring의 Dispatcher Servelt이 작동
3) FrontController인 Dispatcher Servelt이 개발자가 구현한 Controller들을 탐색, 처리 책임 위임


Servlet이란?

  • 서블릿 자바 코드
@WebServlet(name = "helloServelt", urlPatterns = "/hello")
public class HelloServelt extends HttpServelt {
	@Overrride
    protected void service(HttpServeltRequest request, HttpServeltResponse response){ 
    // 애플리케이션 로직
    }
}
  • urlPattern(/hello)의 URL이 호출되면 서블릿 코드가 실행된다.
  • 개발자는 서블릿을 통해 Http 스펙을 매우 편리하게 사용할 수 있게 됐다.

Servelt이란 웹 어플리케이션을 위한 JAVA 클래스 구조를 가진 자바 서버 프로그래임이다. 이것이 왜 필요하냐면 웹페이지를 서버에서 동적(프로그램 코드가 실행)으로 생성하기 위함이다.

컨테이너에 의해 실행되면, 개발자가 임의로 프로그래밍을 하는 것이 아닌, 특정 클래스를 상속받아 구현을 자동으로 생성해 주는 구조이다. 그래서 개발자가 편하게 웹구동을 위한 개발을 할 수 있다.

일반적으로 Request 요청(HttpServletRequest)이나, Response 응답(HttpServletResponse)을 위한 Servelt 객체들은 javax.servlet.http.HttpServelt 클래스를 상속받아 구현한다.


컨테이너란?

컨테이너란 서블릿 객체의 생성, 초기화, 호출, 소멸까지의 인생주기(Life Cycle)를 관리하는 것이다.

서블릿 컨테이너는

1) 요청(Request)이 들어올 때마다
2) 새로운 자바 스레드를 만든다!
3) 그리고 이 스레드가 servlet을 호출한다. (-> 향후 스레드 Pool을 만들어서 스레드 생성 비용을 줄인다.)


서블릿 컨테이너의 기본 5가지 기능을 제공한다.

1) 네트워크 통신
2) 서블릿 객체 인생주기 관리
3) 서블릿 객체 싱글톤으로 관리
4) JSP도 서블릿으로 변환 되어서 사용
5) 동시 요청을 위한 멀티 쓰레드 처리 지원

우리가 알고 있는 대표적인 Servlet Container가 있다. 바로 WAS의 대표주자, Tomcat이다~

지금까지 사용 많이 한 톰캣은
war파일을 java파일에서 Class로 만들고 컴파일하고 메모리에 올려 servlet객체를 만들었던 것이다.


서블릿 동작과정

서블릿 컨테이너는 사용자로부터 요청을 받을 때 마다 요청을 처리할 스레드를 생성한다.(요청 request : 1 Thread)

그리고 그 스레드에서 필요한 서블릿 메소드를 호출하게 되는 것이다.

그렇다고 해서 스레드를 무제한으로 생성하기만 하는 것은 아니고(메모리 비용이 많이 들기때문에) 컨테이너 내부에 Thread Pool(스레드풀)에 스레드를 미리 할당하고, 요청할 때 꺼내 재사용하는 것이다.

✳️ 참고로, Tomcat에서는 기본적으로 클라이언트의 요청을 받을 받기 위해 200개의 Thread를 Thread Pool(스레드풀)에 생생해 둔다.

그리고 서블릿 객체는 싱글톤으로 관리된다.
이것도 요청이 올때마다 계속 객체를 생성하는것은 비효율이기 때문이다.

서블릿 메모리 비효율을 막기 위한 장치
1) 스레드풀
2) 싱글톤

즉, 최초 로딩 시점에 서블릿 객체를 미리 만들어 두고 재활용(스레드풀)하며 모든 요청은 동일한 서블릿 객체 인스턴스(싱글톤)에 접근하게 됩니다.


<김영한 서블릿 컨테이너 was 구조>

서블릿 컨테이너의 동작 방식

1) 사용자가 URL을 클릭하면 HTTP Request를 Servlet Container에 보낸다.
2) Servlet Container는 HttpServletRequest, HttpServletResponse 두 객체를 생성한다.
3) 사용자가 요청한 URL을 분석하여 어느 서블릿에 대한 요청인지 찾는다.
4) 컨테이너는 서블릿 service()메소드를 호출하며, POST/GET 여부에 따라 doGet() 또는 doPost()가 호출된다.
5) doGet()이나 doPost() 메소드는 동적인 페이지를 생성한 후 HttpServletResponse 객체에 응답을 보낸다.
6) 응답이 완료되면 HttpServletRequest, HttpServletResponse 두 객체를 소멸시킨다.


서블릿 생성주기(Servlet Lifecycle)

init(): 서버가 켜질 때 한번만 실행
service(): 모든 유저들의 요청들을 받는다.
destroy(): 서버가 꺼질 때 한번만 실행

서블릿 컨테이너는 클라이언트로부터 처음 요청이 들어오면 현재 실행할 서블릿이 최초의 요청인지 판단한고 없으면 해당 서블릿을 새로 생성한다. 이 작업은 최초 1회만 일어난다.

init() 해당 사용자 서블릿이 최초 생성되고 바로 호출되는 메소드이다.

service() 최초의 요청이든 2번째 요청이든 계속 호출되는 메소드이다.

여기에서 서블릿컨테이너가 종료된다면 사용자 정의 HttpServlet의 destroy()가 호출될 것이다.


서블릿 컨테이너는 IoC 컨테이너

서블릿의 실행 순서는 개발자가 관리하는게 아닌 서블릿 컨테이너가 관리를 한다. 즉 서블릿에 의해 사용자가 정의한 서블릿 객체가 생성되고 호출되고 사라진다.

이렇게 개발자가 아닌 프로그램에 의해 객체들이 관리되는 것을 IoC(Inversion of Control)이라고 한다.


서블릿 인터페이스

1) Servlet

Servlet은 서블릿 프로그램을 개발할 때 반드시 구현해야 하는 메서드를 선언하고 있는 인터페이스이다. 이 표준을 구현해야 서블릿 컨테이너가 해당 서블릿을 실행할 수 있다.

2) GenericServlet

GenericServlet은 Servlet인터페이스를 상속하여 클라이언트-서버 환경에서 서버단의 애플리케이션으로서 필요한 기능을 구현한 추상 클래스이다. service()메소드를 제외한 모든 메서드를 재정의하여 적절한 기능으로 구현했다. GenericServlet클래스를 상속하면 애플리케이션의 프로토콜에 따라 메서드 재정의 구문을 적용해야 한다.

3) HttpServlet

일반적으로 서블릿이라하면 거의 대부분 HttpServlet을 상속받는 서블릿을 의미한다. HttpServlet은 GenericServlet을 상속받았으며, GenericServlet의 유일한 추상 메서드인 service를 HTTP 프로토콜 요청 메서드에 적합하게 재구현해놨다.

이미 DELETE, GET, HEAD, OPTIONS, POST, TRACE를 처리하는 메소드가 모두 정의되어 있다.



참고

profile
배운 것을 기록합니다.

0개의 댓글