Container란(= Web Container, Servlet Container)Container가 주는 장점1. Communication Support2. Servlet Lifecycle Management3. Multithreading support4. Declaraitive Security5. JSP Support컨테이너가 요청을 처리하는 과정Servlet이란?서블릿의 등장 배경서블릿의 역할1. 요청 전달(From WAS TO Controller)2. JSP 생성MVC Pattern in ServletServlet의 Life CycleCustom Servlet등록하기web.xml이용annotation이용(@WebServlet)WebApplicationInitializer
Container란(= Web Container, Servlet Container)
- 서블릿 컨테이너(=자바 어플리케이션)는 서블릿을 제어함(Servlet은 main() 메서드가 없음)
- Tomcat이 컨테이너의 한 예임. Tomcat은 웹서버(Http protocol을 지원)이면서 웹 컨테이너(Supports JSP/Servlet API. = Servlet Container)
- Web Server(like Apache)가 request를 받게 되면(정적 리소스에 대한 request가 아니라면) web server는 해당 리퀘스트를 Container에게 넘겨줌( servlet에게 바로 넘겨주지 않고 servlet을 운용하고 있는 container에게 넘겨줌 )
- Container가 Servlet의 doGet(), doPost()를 호출하는 것임
.png?table=block&id=13116531-b145-4f0f-9645-3db4e1af906a&cache=v2)
Container가 주는 장점
Container 덕분에 threading, security, networking에 대해서 신경 쓰지 않고 business logic에만 집중할 수 있음
1. Communication Support
- 서블릿이 웹 서버와 통신하는 것을 쉽게 해줌
- ServerSocket 생성, listen on a port, create streams 등등의 작업들을 맡아서 해줌
- 컨테이너는 웹 서버와 자기 자신 간의 사용하는 프로토콜을 알고 있기에 서블릿은 아파치 웹 서버와 web application code사이의 API에 대해서 알필요가 없음
- 비즈니스 로직만 처리하면 됨!
2. Servlet Lifecycle Management
- 컨테이너가 서블릿의 생명주기를 관리함
- 클래스 로딩
- 서블릿의 객체 생성과 초기화 (
init( )
) - 서블릿의 메서드
service()
호출 - 서블릿 객체를 garbage collection이 되도록 만들기 (
destroy( )
)
- 컨테이너 덕분에, 자원 관리에 대해서 걱정하지 않아도 됨
3. Multithreading support
- 서블릿이 요청을 받을 때 마다 자바 스레드를 컨테이너가 만들어 줌
- 서블릿이 클라이언트 요청에 대해 작업이 완료 되면 해당 스레드는 종료됨
- 그러나 thread safety가 보장되는 것은 아님
4. Declaraitive Security
- XML(web.xml)을 이용하여 보안 관련 설정을 할 수 있음. 하드 코딩하지 않고
5. JSP Support
- JSP code를 Java로 바꿔 주는 역할도 함
컨테이너가 요청을 처리하는 과정

- 클라이언트가 요청을 보냄
- 컨테이너가 해당 요청이 서블릿에 대한 것임을 알고
HttpServletRequest
,HttpServletResponse
오브젝트를 만듦
- 컨테이너가 요청의 URL을 보고 알맞은 서블릿을 찾고, 해당 요청에 대한 스레드를 만들고 거기에 요청 할당. request, response 오브젝트도 넘겨줌
- 컨테이너가 서블릿의 service() 메서드를 호출함
- 스레드가 완료되면, 컨테이너는 servlet response → HttpResponse로 변환하여 클라이언트에게 보내줌
Servlet이란?
[Baeldung] Introduction to Java Servlets
간단하게 말해서, Servlet은 request를 받고 처리해서 response로 응답하는 것을 담당하는 클래스다
서블릿의 등장 배경
POST /save HTTP/1.1 HOST: localhost:8080 Content-Type: application/x-www-form-urlencoded username=ndy&age=20
- HTTP
POST
를 통해 위와 같은 요청 메시지가 서버에 전달되면 서버는 아래의 모든 일을 수행해야한다. - TCP/IP 연결 대기 → 소켓 연결
- HTTP 요청 메시지 파싱 (스타트 라인, 헤더, 메시지 바디 파싱)
- 비즈니스 로직 실행
- HTTP응답 메시지 생성(스타트 라인, 헤더, 미시지 바디 생성)
- TCP/IP에 응답 전달 → 소켓 종료
웹 요청시 발생하는 공통되는 처리를 담당하는 인터페이스 (Servlet)을 만들고 그것을 WAS(e.g. tomcat)가 처리하게 하자!
개발자들이 진짜 집중해야하는 비즈니스 로직 - 가운데 있는 처리 로직에 더 집중 할 수 있게 된다.
- 서블릿은 CGI를 개선하여
- 요청마다 Process가 아닌 Thread를 생성함
- Singleton 패턴 적용
서블릿의 역할
1. 요청 전달(From WAS
TO Controller
)


- HTTP 요청이 서버에 도착하면 일반적으로 인증, 로깅, 감사와 같은 필터링 작업을 수행하는 필터 리스트를 통과함. 요청이 모든 필터를 통과하면 애플리케이션 서버는 특정 패턴과 일치하는 URI를 포함하는 요청을 처리할 수 있게 등록된 서블릿으로 요청을 넘겨줌
- 서블릿이 요청에 대한 처리를 마치면 HTTP 응답은 해당 HTTP 요청을 처리한 같은 필터 세트를 통과한 후 클라이언트로 다시 전송
- Client에서 들어온 요청을 WAS에서 받아서 특정 Service에 전달해주려고 할 때 그 사이에 들어가는 부분임
- Service에서 받아온 데이터를 가지고 servlet을 이용하여 특정로직을 처리하면 JSP와 같은 페이지(Http, 혹은 리소스)를 만들어서 반환 가능함
- 최근에는 Jakarta Servlet으로 이름 바뀜(이전에는 Java servlet)
- WAS, Web Container안에서 구동이 됨

- Servlet은 하나의 규약이고(specification) 여러 Web Server 벤더(Tomcat ... )에 공통적으로 적용하여 개발할 수 있도록. 그리고 어플리케이션 개발자(우리)들도 공통의 규약을 가지고 개발을 할 수 있는것
- 예를 들어 Servlet 상속받아 어떠한 메서드를 작성하게 되면, Web Application Server 개발자들이 내부적으로 Web Container를 띄우고 해당 Servlet의 메서드를 호출하도록 만들어 두었기에 그 메서드가 호출되게 되는 것 — 일종의 Framework같은 것
- WAS 개발한다고 해보면, TCP/IP 커넥션 맺는것 부터 해서 http 데이터 들어온것 파싱, http 프로토콜 자체를 개발하는 서버를 개발
- 비즈니스 로직 부분(Servlet)
- 실제 웹 서버로서 HTTP요청 파싱, 응답처리, 네트워크 열고 닫는 부분(Container)
2. JSP 생성

- JSP도 코드를 작성함(동적 컨텐츠 작성 가능함). Servlet이 JSP를 만들어 주고 WAS가 JSP를 읽어서 컴파일하고 렌더를 하면 html 컨텐츠를 만들어 주어 응답이 반환됨
MVC Pattern in Servlet

- MVC 패턴은 웹 어플리케이션을 만들 때, 기능을 모델 뷰 컨트롤러로 분리를 해서 각 컴포넌트의 관심사를 분리 시킨 것
- 화면(presentation layer), 데이터 처리를 담고 있는 부분 으로 분리를 한 것
- View : 모델이 담고 있는 데이터를 시각적으로 보여주는 역할을 함 — JSP
- Model : 모델은 자바 객체 또는 Pojo로 데이터를 담고 있음, 비즈니스 로직도 — Java Bean(POJO)
- Controller : 모델과 뷰를 연결하기 위한 매개체. 사용자의 입력/요청을 받아 모델의 상태를 변경해주고 그에 따른 뷰를 업데이트 해줌 — Servlet
Servlet의 Life Cycle

- Thread별로 Servlet을 만드는 건 아니고 Servlet의 메서드에 요청
- Servlet 한번 만들어지고 매번 요청 올 때마다 doGet, doPost 가 호출이 됨
- 초기화 : 첫 요청 시 -
init( )
- 요청 받으면 -
service( )
- HTTP Servlet → doGet(), doPost()
- 소멸 -
destroy( )
→ gc 됨
Custom Servlet등록하기
- Tomcat을 켜고 아래와 같은 방식으로 Servlet등록해서 사용하는 방법은 톰캣이 미리 설치되어 있고 톰캣이 구동되고 톰캣에다가 war를 배포하는 방식 — old한 방식
web.xml이용
<web-app> <servlet> <servlet-name>welcome</servlet-name> <servlet-class>servlets.WelcomeServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>welcome</servlet-name> <url-pattern>/welcome</url-pattern> </servlet-mapping> </web-app>
annotation이용(@WebServlet)
@WebServlet(value = "/*") // loadOnStartUp : 1 이면 request들어오기도 전에 켜면서 Servlet구동함. -1이면 request가 들어올 때 init()이 호출됨 public class TestServlet extends HttpServlet { private static final Logger logger = LoggerFactory.getLogger(TestServlet.class); @Override public void init() throws ServletException { super.init(); logger.info("Init Servlet"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String requestUri = req.getRequestURI(); logger.info("Got Request from : {}", requestUri); // super.doGet(req, resp); PrintWriter writer = resp.getWriter(); writer.println("Hello Servlet!"); } }
WebApplicationInitializer
- WebApplicationInitializer 라는 interface를 구현하면서 WAS가 classpath에 있는 모든 클래스를 스캔하면서 구현체가 있으면 시작. 인스턴스화 시키고 온스타트라는 메서드를 실행하게 됨
public class PrgmWebApplicationInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { var servletRegistratrion = servletContext.addServlet("test", new TestServlet()); servletRegistratrion.addMapping("/*"); servletRegistratrion.setLoadOnStartup(1); } }