BackEnd/Servlet, JSP

[Servlet, JSP] Servlet Life Cycle : Servlet 생명 주기

샤아이인 2022. 1. 14.

인터넷에서 찾을수 있는 글 중에서 가장 자세하게 설명하려 노력하였습니다.

진짜 영혼을 갈아서 설명해 보았습니다.

도움이 되셨다면 좋아요 하나 부탁해요~~

Servlet Life Cycle

클라이언트가 Servlet에 요청을 하면, Servlet은 바로 호출이 되지 않습니다.

Servlet은 객체를 생성하고 초기화 작업을 거친 후, 요청을 처리하는 생명 주기를 갖고 있습니다.

 

우선 다음 그림을 살펴봅시다!

◆ 클라이언트로부터 처리 요청 받음

클라이언트가 웹 브라우저를 통해 요청을 보내면 웹서버가 이를 받아서 요청 정보안에 있는 헤더안에 있는 URI를 분석합니다.

이때 요청받은 페이지가 서블릿 이면 서블릿 컨테이너에게 처리를 넘깁니다.

서블릿 컨테이너는 요청받은 서블릿을 WEB-INF/classes 나 WEB-INF/lib 에서 찾아서 실행준비를 합니다.

 

 최초의 요청 여부 판단

서블릿 컨테이너는 현재 실행할 서블릿이 최초의 요청인지를 판단합니다.

실행할 서블릿 객체가 메모리에 없으면 최초의 요청이고, 이미 있다면 최초의 요청이 아닌것으로 판단합니다.

 

2) 서블릿 객체 생성

서블릿 컨테이너는 요청받은 서블릿이 최초의 요청이라면 해당 1) 서블릿을 메모리에 로딩하고 2) 객체를 생성 합니다.

서블릿은 최초의 요청이 들어왔을때 한번만 객체를 생성하고, 이때 생성된 객체를 계속 사용합니다 => singleton으로 관리

 

3) ServletConfig 객체 생성

web.xml 파일에 <servlet> 태그를 사용하여 서블릿에 관한 환경설정을 할 수 있습니다.

<servlet> 태그 안에는 서블릿의 이름, 초기 파라미터, 객체 생성 여부 등 여러 속성을 설정할 수 있습니다.

이처럼 web.xml의 <servlet> 태그에 설정한 정보를 서블릿 페이지 내에서 추출할 때는 ServletConfig 객체에서 제공하는 메서드를 사용합니다.

ServletConfig 객체는 서블릿이 실행될때 자동으로 생성됩니다. 이후 init() 메서드의 인자로 전달됩니다.

 

4) init(ServletConfig) 메서드 실행

init()은 서블릿 객체가 생성된 다음에 호출되는 메서드로서, Servlet 인터페이스에 선언되어 있고, 기능은 GenericServlet 클래스에서 구현되어 있습니다.

init() 메서드는 처음 요청시 서블릿 객체가 생성된 다음 호출되므로 주로 서블릿 객체의 초기화 작접이 구현되어 있습니다.

 

5) HttpServletRequest, HttpServletResponse 객체 생성

init()메서드 실행이 끝난 다음에는 최초의 요청이든, 그렇지 않든 서블릿 실행 요청이 들어올 때마다 실행되는 작업으로, 서블릿 컨테이너는 HttpServletRequest, HttpServletResponse 객체를 생성합니다.

 

6) service(HttpServletRequest, HttpServletResponse) 메서드 실행

service()메서드는 실행하는 서블릿의 요청 순서에 상관없이 클라이언트의 요청이 있을 때마다 실행됩니다.

따라서 service() 메서드에는 실제 서블릿에서 처리해야 하는 내용이 구현되어 있습니다.

 

service() 메서드는 Servlet 인터페이스에 선언되어 있고, GenericServlet 클래스에 abstract 메서드로 선언되어 있으므로, HttpServlet 클래스에 메소드 몸체가 구현되어 있습니다. 다음 그림을 살펴보시죠!

 

출처 -&amp;amp;amp;nbsp; http://books.gigatux.nl/mirror/beaweblogic8.1/0672324873_ch14lev1sec6.html
 

따라서 일반적으로 개발자는 HttpServlet 클래스를 상속받고 service() 메서드를 오버라이딩 하여 개발하게 됩니다.


좀더 deep dive 해볼까요?

바로 위에서 일반적으로 service() 메서드를 재정의 하여 사용한다고 했는데, 재정의 하지 않을때가 있습니다.

 

바로 HttpServlet에 구현된 service() 메서드를 그대로 실행하고 싶을 때 입니다!

 

다음은 HttpServlet이 가지고 있는 두 가지 형태의 service() 메서드 입니다. 색으로 구별한점 기억해 주세요!

1) protected void service(HttpServletRequest req, HttpServletResponse resp)

2) public void service(ServletRequest req, ServletResponse resp)

 

둘 중에서 서블릿 요청이 있을때 마다 실행되는 메서드는 2번 형태의 service() 입니다.

그런데 2번 형태의 service() 는 단순히 같은 객체에 있는 1번 형태의 service() 를 호출만 해줍니다.

 

다음 코드를 살펴볼까요? 다음 코드는 2번 service() 입니다. 내부에서 1번 service()를 호출하고 있죠!

public abstract class HttpServlet extends GenericServlet{

    생략 ...

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {

        HttpServletRequest  request;
        HttpServletResponse response;

        try {
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException e) {
            throw new ServletException(lStrings.getString("http.non_http"));
        }
        service(request, response);  1번 service 호출
    }

    생략....
}
 

1번 형태의 service() 메서드는 클라이언트의 실행 요청에 따라 서로 다른 메서드를 호출하도록 구현되어 있습니다.

 

클라이언트가 서버에 서비스를 요청했다는 것은 => 요청정보 메시지를 보냈다는것 입니다.

요청정보 메시지 첫 줄에는 3개의 정보가 있는데요, 이때 첫 단어가 요청메서드에 대한 정보입니다.

대표적으로 GET, POST, PUT, DELETE 등 이 있습니다.

 

앞서 1번 형태의 service() 메서드는 바로 이 요청방식 정보를 추출한 후, 추출되는 요청방식에 따라 서로 다른 메서드를 호출하도록 구현되었습니다. 이때 호출되는 메서드는 HttpServlet 클래스에서 선언하고 있는 다음 메서드 들 입니다.

클라이언트가 GET 방식으로 요청했다면 doGet()을, POST 방식으로 요청했다면 doPost() 메서드를 호출하게 됩니다.

 

만약 똑같은 URI 요청을 요청 방식에 따라 서로 다르게 구현하려면 HttpServlet 클래스의 service() 메서드가 실행되도록 한 다음,

service()가 service() 메서드를 호출합니다. 이후 doGet() 또는 doPost() 메서드 등이 실행되도록 오버라이딩 하면 됩니다.

 

service() 메서드를 재정의 할지, doGet(), doPost() 매서드를 재정의할지는 개발하는 상황에 맞춰 선택해야 합니다.

만약 doGet(), doPost() 와 같이 메서드 구분이 필요없이 그냥 출력해보고 싶다면, 위에서 말했듯 일반적인 service()메서드를 오버라이딩 하면 됩니다

댓글