서블릿 객체의 상속 구조
서블릿 클래스 간의 관계
서블릿을 구현할 때 반드시 상속받아야 하는 클래스가 있는데요. 바로 javax.servlet.http 패키지에 있는 HttpServlet 클래스입니다. HttpServlet에는 웹상에서 클라이언트 요청이 있을 때 해당 서블릿을 실행하는 모든 조건이 포함되어 있습니다. 그래서 모든 서블릿은 반드시 HttpServlet을 상속받아야 합니다. HttpServlet를 상속받지 않은 클래스는 서블릿이라 할 수 없고, 따라서 클라이언트가 실행을 요청하여도 실행되지 않습니다.
모든 서블릿의 상위에 있는 HttpServlet, GenericServlet, Servlet에 대해 간단하게 정리해보겠습니다.
Servlet 인터페이스
Servlet은 서블릿 프로그램을 개발할 때 반드시 구현해야 하는 메소드를 선언하고 있는 인터페이스입니다. init(), service(), destroy(), getServletConfig(), getServletInfo() 등 5개의 메소드를 선언하고 있는데요. 이는 서블릿 프로그램 실행의 생명주기와 연관된 메소드들입니다.
GenericServlet 클래스
GenericServlet은 Servlet 인터페이스를 상속하여 클라이언트-서버 환경에서 서버단의 애플리케이션으로서 필요한 기능을 구현한 추상 클래스입니다. service() 메소드를 제외한 모든 메소드를 재정의하여 적절한 기능으로 구현하였습니다. GenericServlet 클래스를 상속하면 애플리케이션의 프로토콜에 따라 메소드 재정의 구문을 적용해야 합니다.
HttpServlet 클래스
HttpServlet 클래스는 GenericServlet 클래스를 상속하여 service() 메소드를 재정의함으로써 HTTP 프로토콜에 알맞은 동작을 수행하도록 구현한 클래스입니다. 즉, HTTP 프로토콜 기반으로 브라우저로부터 요청을 전달받아서 처리하도록 하는 클래스입니다. service() 메소드에는 요청방식에 따라 doGet(), doPost() 등 정해진 사양의 메소드가 호출되도록 구현되어 있습니다.
HttpServlet 클래스를 상속하여 웹서버 기반의 서블릿 프로그램을 구현할 때 반드시 재정의해야 하는 메소드는 없으며, 어떠한 요청방식을 지원하는 서블릿인지에 따라서 필요한 메소드를 재정의하여 구현합니다.
서블릿 실행 순서 및 서블릿 객체의 생명 주기
서블릿 실행 순서
서블릿의 실행 순서를 이해하려면 IoC라는 개념을 알아야 합니다. Java SE 프로그램은 개발자가 main() 메소드 안에 구현한 순서대로 실행됩니다. 즉, 프로그램이 실행되는 순서를 개발자가 제어합니다. 그러나 Java EE 기반 프로그램은 실행의 흐름을 개발자가 제어하는 것이 아니라 컨테이너가 제어합니다.
이처럼 개발자가 아닌 제3자가 프로그램의 실행 흐름을 제어하는 것을 IoC(Inversion of Control), 우리말로 번역하면 "제어의 역전"이라고 합니다. 우리가 개발할 서블릿도 여기에 속합니다. 따라서 Java EE 기반 프로그램을 개발할 때는 먼저 애플리케이션 컨테이너들이 프로그램을 어떤 순서로 동작시키는지 알고 해당 순서에 맞게 개발해야 합니다.
다음은 서블릿의 실행 순서와 설명입니다.
1) 클라이언트로부터 처리 요청 받음: 클라이언트가 웹 브라우저를 통해 요청을 보내면 웹서버는 이를 받아서 요청정보의 헤더 안에 있는 URI를 분석합니다. 이때, 요청받은 페이지가 서블릿이면 서블릿 컨테이너에 처리를 넘깁니다. 서블릿 컨테이너는 요청받은 서블릿을 WEB-INF/classes나 WEB-INF/lib에서 찾아서 실행 준비를 합니다.
2) 최초의 요청 여부 판단: 서블릿 컨테이너는 현재 실행할 서블릿이 최초의 요청인지를 판단합니다. 실행할 서블릿 객체가 메모리에 없으면 최초의 요청이고, 이미 있으면 최초의 요청이 아닌 것으로 판단합니다.
3) 서블릿 객체 생성: 서블릿 컨테이너는 요청받은 서블릿이 최초의 요청이라면 해당 서블릿을 메모리에 로딩하고 객체를 생성합니다. 일반 자바 객체는 new 명령문으로 여러 개의 객체를 언제든지 직접 생성할 수 있지만, 서블릿은 최초 요청이 들어왔을 때 한 번만 객체를 생성하고 이때 생성된 객체를 계속 사용합니다.
4) init() 메소드 실행: init()는 서블릿 객체가 생성된 다음에 호출되는 메소드로서, Servlet 인터페이스에 선언되어 있고, 기능은 GenericServlet 클래스에 구현되어 있습니다. init() 메소드는 처음 요청 시 서블릿 객체가 생성된 다음 호출되므로 주로 서블릿 객체의 초기화 작업이 구현되어 있습니다. GenericServlet 클래스에 구현된 내용을 바꾸고 싶다면 init() 메소드를 재정의하여 원하는 내용으로 변경하면 됩니다.
5) service() 메소드 실행: service() 메소드는 실행하는 서블릿의 요청 순서에 상관없이 클라이언트의 요청이 있을 때마다 실행됩니다. 따라서 service() 메소드에는 실제 서블릿에서 처리해야 하는 내용이 구현되어 있습니다. service() 메소드는 Servlet 인터페이스에 선언되어 있고, GenericServlet 클래스에 abstract 메소드로 선언되어 있으므로, HttpServlet 클래스에 메소드 몸체가 구현되어 있습니다. HttpServlet 클래스에 구현된 내용을 변경하고 싶다면 service() 메소드를 재정의하여 원하는 내용으로 변경하면 됩니다.
service() 메소드가 끝나면 서버에서의 실행은 끝납니다. 서버 프로그램 실행이 완료된 후에는 서블릿 컨테이너가 실행결과를 웹서버에 전달하고, 웹서버는 서비스를 요청한 클라이언트에 응답합니다. 이로써 웹에서 하나의 요청에 대한 처리가 완료됩니다.
콜백 메소드와 서블릿 객체의 생명주기
여기서 말하는 콜백 메소드(callback method)란, 어떤 객체에서 어떤 상황이 발생하면 컨테이너가 자동으로 호출하여 실행되는 메소드를 의미합니다. 이러한 콜백 메소드들이 서블릿을 실행합니다. 바로 앞에서 설명했던 HttpServlet 클래스를 상속받은 다음 재정의한 init(), service()가 콜백 메소드에 속합니다. 이 메소드들은 서블릿 객체에 어떤 상황(이벤트)이 발생하면 호출됩니다.
그런데 init()와 service() 메소드 말고 서블릿의 콜백 메소드가 또 하나 있습니다. GenericServlet 클래스에 선언되어 있는 destroy() 메소드입니다. destroy()는 메모리에서 서블릿 객체가 삭제될 때 호출되는 메소드입니다. 객체가 삭제될 때 호출되므로 자원을 해제하는 작업을 수행합니다.
다음은 서블릿의 콜백 메소드에 대한 설명을 표로 정리한 것입니다.
메소드 이름 | 메소드가 실행되는 시점 | 실행 횟수 | 기능 구현 |
---|---|---|---|
init() | 클라이언트로부터 최초로 서블릿 요청이 있을 때 실행 | 1 | 초기화 작업 |
service() | 클라이언트로부터 요청이 있을 때마다 실행 | n | 실제 서블릿이 처리해야 하는 작업 |
destroy() | 서블릿 객체가 메모리에서 삭제될 때 실행(서비스나 서버 중지 시) | 1 | 자원 해제 작업 |
서블릿 객체의 생성
서블릿 객체가 메모리에 생성되는 시점은 서버 입장에서 클라이언트로부터 최초로 서블릿 실행 요청이 있을 때입니다. 클라이언트 입장이 아니고 서버 입장입니다. 어떤 클라이언트가 최초로 요청했는지는 중요하지 않습니다.
서버 입장에서 최초로 서블릿 요청이 있을 때, 서블릿 컨테이너는 해당 서블릿 객체를 메모리에 생성한 다음, init() -> service() 순으로 실행합니다. 이후에 같은 서블릿 실행 요청이 있으면 최초 요청 시 생성한 서블릿 객체의 service() 메소드를 실행합니다.
사실 클라이언트로부터 서블릿 요청이 있을 때마다 요청이 최초인지를 판단하는 기준은 객체 생성 여부입니다. 중요한 사실은 요청이 있을 때마다 서블릿 객체를 생성하는 것이 아니고, 최초 요청 때 생성한 서블릿 객체를 계속 사용한다는 것입니다. 서블릿은 한 번 생성한 객체를 재사용해 처리속도, 메모리 부분에서 효율적인 장점이 있습니다.
서블릿 객체의 삭제
최초 요청 시 생성된 서블릿 객체가 삭제되는 시점은 서버를 중지시켜 웹 애플리케이션 서비스를 중지할 때입니다. 웹서버에서는 전체 서비스를 중지할 수도 있고 일부 서비스만 중지할 수도 있습니다. 어떤 상황이든지 서블릿 객체가 삭제되는 시점은 웹서버에서 웹 애플리케이션 서비스가 중지되는 시점입니다. 이때 destroy() 메소드가 호출되어 실행됩니다. 그래서 destroy() 메소드에는 자원 해제하는 내용을 구현하면 알맞습니다.
'웹 프로그래밍 > Servlet & JSP' 카테고리의 다른 글
Servlet 응답 정보 처리 (HttpServletResponse, 한글 응답) (0) | 2021.03.11 |
---|---|
서블릿 구현 및 실행 (web.xml, @WebServlet 설정) (3) | 2021.03.11 |
웹 URL, 웹 애플리케이션 위치 및 구조, web.xml (0) | 2021.03.10 |
웹 서버와 웹 애플리케이션 서버의 차이점 (0) | 2021.03.10 |
웹 문서(정적 컨텐츠, 동적 컨텐츠), 웹 애플리케이션, 웹 서비스 (0) | 2021.03.10 |
댓글