들어가며
이 포스팅에 나오는 내용은 <<Head First Servlets & JSP>>의 네 번째 장, 요청과 응답에 나오는 내용을 정리한 것이다.
서블릿 생성 - 소멸에 대한 5분 정리
서블릿의 일생동안 컨테이너는 서블릿을 관리한다. Request, Response 객체를 생성하고, 새로운 스레드를 만들어 서블릿 service() 메서드를 호출하고, Response 와 Request 객체에 대한 참조를 인자로 넘긴다.
간단하게 정리하면 다음과 같다.
- 사용자가 서블릿에 대한 URL 을 클릭한다.
- 컨테이너는 요청된 리퀘스트가 서블릿이라는 걸 파악하고, 다음 두 객체를 생성한다.
- HttpServletResponse
- HttpServletRequest
- 접수한 요청의 URL 을 분석하여, 어떤 서블릿을 요청했는지 파악한다. (이 때, DD를 참조한다) 그 다음에 해당 서블릿 스레드를 생성하여 Request, Response 참조를 넘긴다.
- 컨테이너는 서블릿 service() 메서드를 호출한다. 브라우저에서 지정한 방식에 따라, doGet() 혹은 doPost()를 호출한다. 만약 브라우저에서 한 요청이 get 이면 doGet, post 면 doPost 를 호출하게 된다.
- 클라이언트에게 응답을 보내기 위해, 서블릿 레드는 response 객체를 사용한다. 작업이 완료되면 컨테이너에게 response 객체 제어가 넘어간다.
- service() 메서드가 끝나면, 스레드는 소멸하거나 스레드 풀로 돌아간다. 그 후에 response, request 객체는 가비지 컬렉션 대상이 될 것이다.
- 클라이언트는 서버에게 응답을 받는다.
더 나아가면
그러나 위에서 서술한 내용이 전부는 아니다. 서블릿의 일생에는 더 많은 것들이 있다.
- 언제 서블릿 클래스를 로딩하는지?
- 서블릿의 생성자는 언제 호출되는지?
- 얼마나 오랫동안 서블릿이 살아 있는지?
- 서블릿은 언제 자원을 초기화하는지?
- 사용한 자원은 언제 깨끗이 청소하는지?
서블릿의 일생은 사실 간단하다. 서블릿은 오직 중요한 하나의 상태를 가진다. 즉, 초기화되었는지 / 아닌지이다. 서블릿이 초기화되지 않았다는 것은, 초기화되는 중(생성자를 실행하거나 init()을 하거나)이거나, 소멸되는 중(destroy() 실행중)이거나, 그것도 아니면 존재하지 않는다는 뜻이다.
서블릿 일생에 있어서 세 번의 중요한 순간
- init()
- 컨테이너는 서블릿 인스턴스 생성. init()호출
- init()은 service()이전에 호출되어야 함
- 클라이언트의 요청을 처리하기 전에, 서블릿을 초기화 할 기회를 주는 것
- 초기화 할 코드가 있다면, init() 메서드를 재정의하면 됨
- service()
- 클라이언트의 요청을 받았을 때, 새로운 스레드를 생성하거나 스레드 풀에서 하나를 가져와서 service() 호출
- 클라이언트의 HTTP 메소드를 참조하여, doGet 을 호출할지 doPost 를 호출할지 판단한다.
- 거의 초기화 할 일이 없다. doPost 나 doGet 을 재정의하면 됨
- doGet() / doPost()
- service() 메서드가 HTTP method 를 참조하여 doGet() / doPost()를 호출한다. 이 이외에는 거의 사용할 경우가 없다.
- 여기에다가 코딩을 하면 됨
- 항상 둘 중 하나는 재정의해야 한다.
서블릿의 인스턴스
또한 요청이 들어올 때마다, 서블릿은 request, response 객체를 생성하고 스레드를 만든다. 인스턴스는 서블릿에서 단 하나만 존재한다. 다수의 스레드를 생성하는 것이다.
그렇다면 LVS 를 두고 다수의 서버가 요청을 받는 상황이라면? 하나의 서버에는 하나의 JVM 이 있을 것이고, 그 JVM 에는 하나의 인스턴스가 존재할 것이다.