이 글은 공부를 하면서 알게 된 내용들을 기록하는 글 입니다. 오류나 고쳐야 할 사항들이 있다면 지적 부탁드립니다!
팀 프로젝트를 통해 개발한 코드들을 리팩토링하고 공부하는 과정에서 `HttpServletRequest`, `HttpServletResponse`와 같이 `Servlet`이라는 단어를 많이 접할 수 있었다.
`Servlet`이란 무엇일까? 한 번 알아보자.
✅ Servlet이란?
Servlet(서블릿)이란 client로부터 받은 Request(요청)을 처리하고, 그 결과(Response)를 반환하는 Java 프로그램이다.
🔥 Servlet의 LifeCycle
Servlet의 생명주기(life cycle)는 Servlet container에 의해 관리된다.
`javax.servlet` 패키지의 `Servlet` 인터페이스를 구현한 객체들이 여기에 속한다.
Servlet container에서 Servlet의 생명주기를 관리하기 위해서는 `Servlet` interface의 세 메서드(init, service, destroy)를 정의해야 한다.
package jakarta.servlet;
import java.io.IOException;
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
init()
`Servlet.init()`은 생명 주기 중 `초기화 단계`에 Servlet container에 의해 호출되며, 생명 주기동안 딱 한 번 실행된다.
일반적으로 Client의 최초 요청 시점에 Servlet 객체가 container에 생성되고, `init()` 메서드를 통해 초기화를 진행한다.
Servlet 객체 당 한 번씩만 호출되는 이유는 싱글톤으로 관리되기 때문인데, 이는 초기화 단계에서 많은 비용이 들고 계속해서 사용할 수 있는 객체이기 때문이다.
service()
client의 Request(요청)으로 인해 Servlet의 `service()` 메서드가 실행되며, 비지니스 로직을 수행한다.
HTTP Method(GET, POST, PUT, PATCH, DELETE...) 확인 후, 해당하는 메서드(doGet, doPost, doPut...) 을 호출한다.
client가 요청한 데이터들을 모아 보기위해 `ServletRequst`를 사용하며, 요청에 대한 응답 내용들을 만들기 위해 `ServletResponse`를 사용한다.
각각의 요청은 별도의 thread에서 처리하는데, Servlet 객체는 동시에 여러 개의 thread를 제공할 수 있지만 thread-safe하지 못하다.
destroy()
Servlet의 생명 주기 중 단 한 번 실행되며, Servlet 인스턴스의 종료를 뜻한다.
`destory()` 메서드가 실행되면, Servlet container는 Servlet 인스턴스를 종료하며 점유하고 있던 자원들을 할당 해제한다.
✅ Servlet container
위에서 이야기한 `Servlet` 인터페이스를 구현하면 바로 Servlet 객체로 등록되어 사용이 가능할까?
아니다. Servlet 객체들의 생명 주기(life cycle) 등을 관리할 관리자가 필요하다. `Servlet container`가 바로 이 역할을 담당한다.
`Servlet container`는 client가 요청한 Request를 받아, 적절한 처리를 통해 Response를 할 수 있게끔 도와주며, 대표적인 예시로 `Tomcat`을 들 수 있다.
🔥 Servlet container의 동작 방식
1. Client로부터 온 요청(HTTP Request)를 Servlet container로 전달
2. Servlet Container에서는 `HttpServletRequest`, `HttpServletResponse` 두 객체 생성
3. `web.xml`을 통해 Request를 처리할 Servlet 객체를 찾은 후, request 전달
4. 해당 Servlet은 `service()` 메서드를 호출하고, HTTP Method(GET, POST, PUT...)에 알맞는 메서드(doGet(), doPost(), doPut()...)을 호출
5. 메서드는 동적 페이지를 생성한 후, `HttpServletResponse` 객체에 응답을 보냄
6. 응답 완료 후 `HttpServletRequest`, `HttpServletResponse` 두 객체의 할당을 해제
🔥 Servlet container의 역할
1. 웹 서버와의 통신 지원
Servlet container는 socket을 만들고, port를 listen과 같은 API를 제공하여, 웹 통신을 위한 복잡한 과정들을 대신해준다.
덕분에 개발자는 복잡한 과정을 거치지 않고도 통신을 할 수 있다.
2. Servlet의 생명 주기(life cycle) 관리
Servlet container는 Servlet 인스턴스들의 초기화 ~ 할당 해제까지의 생명 주기(life cycle)을 관리한다.
3. Multi-thread 지원 및 관리
Servlet container는 Request(요청)이 올 때마다 Java thread를 생성하여 요청을 처리한다.
HTTP 서비스의 메서드를 실행하고나면, thread는 자동으로 소멸한다.
이러한 thread들을 관리해야 하지만, 다중 thread를 생성 & 관리해주기 때문에, thread의 안정성에 대해 걱정하지 않아도 된다.
4. 보안 서비스
리소스 액세스의 승인 및 인증을 처리한다.
✅ 참고 자료 & 링크
- https://www.geeksforgeeks.org/life-cycle-of-a-servlet
- https://velog.io/@han_been/Servlet
- https://mangkyu.tistory.com/14