[Spring] Spring Servlet과 Servlet Container란? (DispatcherServlet)

Spring Servlet이란?


Spring Servlet은 웹 애플리케이션에서 클라이언트의 요청을 처리(요청을 받고, 응답을 반환)하는 작업을 한다.

일반적으로 이 Servlet을 Spring MVC 패턴에서 DispatcherServlet이라고 불린다. (Servlet은 일반적인 개념과 인터페이스를 나타내고, DispatcherServlet은 Spring의 특정 구현을 나타낸다.)

용어가 좀 헷갈릴 수 있는데 간단히 말하면 DispatcherServlet은 Servlet이지만 모든 Servleet이 DispatcherServlet은 아니다.

 

Spring에서 DispatcherServlet의 역할은 Spring 기반 웹 애플리케이션의 앞단(front controller)에서 웹 요청을 적절한 Controller에 분배하는 역할을 한다.

 

아래 그림을 보면서 동작 방식을 보면 이해하기가 훨씬 쉬울 것이다.

 

 

DispatcherServlet 동작 방식


https://velog.io/@neity16/6-%EC%8A%A4%ED%94%84%EB%A7%81-MVC-6-%EC%8A%A4%ED%94%84%EB%A7%81-MVC-%EA%B5%AC%EC%A1%B0-DispatcherServlet-HandlerMapping-HandlerAdapter-viewResolver

 

  1. DispatcherServlet에서 클라이언트의 HTTP 요청을 수신한다. (DispatcherServlet이 요청을 가장 먼저 받는다.)
  2. 요청을 받으면, DispatcherServlet은 HandlerMapping을 참조해 요청을 처리할 Controller를 찾는다. HandlerMapping은 클라이언트가 요청한 URL, HTTP 메서드, 요청 파라미터 등을 기반으로 적절한 Controller를 선택한다.
  3. 선택된 Controller는 요청을 처리한 뒤, ModelAndView 객체를 DispatcherServlet에 반환한다. 이 객체는 View 이름과 그 View에 전달할 모델 객체를 포함한다.
  4. 반환된 ModelAndView 객체는 ViewResolver에 의해 실제 View 객체로 변환된다. ViewResolver는 View 이름을 기반으로 적절한 View를 찾아내고, 이 View는 클라이언트에게 반환될 최종적인 HTML을 생성한다.
  5. 생성된 HTML은 클라이언트에게 반환된다.

위의 예시에서는 대표적으로 HTML이 생성되는것으로 설명했지만 우리가 흔히 아는 RESTful 웹 애플리케이션을 만든다고 하면 Controller는 ModelAndView 대신에 @ResponseBody 어노테이션이 붙은 객체를 반환하게 되고, 이 객체는 HTTPMessageConverter에 의해 JSON 또는 XML로 변환되어 반환된다. 즉 DispatcherServlet의 설정에 따라서 과정이 변경될 수 있다.

 

 

Servlet이 필요한 이유


간단히 Servlet이 필요한 이유를 말하면 Servlet은 Java 기반 웹 애플리케이션의 핵심 구성 요소이다.

왜냐하면 위에서 보았듯이 Servlet은 클라이언트 HTTP 요청을 처리하고 응답을 반환하는 기본적인 메커니즘 역할을 하기 때문이다.

Servlet 없이 Java로 웹 애플리케이션을 만든다고 하면 할 수는 있지만 그 과정이 훨씬 더 복잡하고 어렵다.

 

If Servlet이 없다면?

1. 클라이언트 요청 처리

클라이언트의 HTTP 요청을 수동으로 분석하고 HTTP 응답을 수동으로 만들어야 한다.

 

2. 생명 주기 관리

위에서는 언급하지 않았지만 Servlet은 Servlet Container가 생명주기를 관리해주는데 이러한 Servlet Container가 존재하지 않아 직접 Servlet을 초기화하고, 메서드를 호출하고, 다시 Servlet을 제거하는 생명 주기 관리를 직접 해줘야 한다. 

 

3. 동시성 관리

Servlet Container는 각 요청에 대해 새로운 스레드를 생성해주기 때문에 Servlet은 여러 요청을 동시에 처리할 수 있다. 만일 Container가 없다면 이러한 동시성 처리도 직접 해줘야 한다.

 

 

이렇게 편리한 기능들을 자동으로 해준다는데 Servlet을 사용하지 않을 이유가 없다. 그리고 저것들을 웹 개발할때마다 전부 직접 구현해줘야 한다???? 너무 최악이다.

 

그래서 Servlet을 이용하면 개발자가 쉽게 웹 애플리케이션을 구축할 수 있도록 도와주기 때문에 필수적이다.

 

 

Servlet Container


Servlet Container는 Servlet들을 관리하는 저장소라고 생각하면 편하다.

Servlet Container는 위에서 잠깐 말했지만 Servlet의 생명주기를 관리, 요청 및 응답 처리, 멀티 스레딩 지원 등등 Servlet Container가 유용한 작업들을 처리하고 있다. 대표적인 Servlet Container는 우리가 흔히 아는 Tomcat이 존재한다. 

 

Servlet Container가 하는 작업을 좀 더 자세히 알아보자.

 

Servlet 생명주기 관리

Servlet Container는 Servlet의 생명주기를 관리(init(), service(), destory() 메서드)하는데 클라이언트의 요청이 오면 init()메서드를 호출해 Servlet을 load한다. 이후 클라이언트의 요청에 따라 service()메서드를 실행해 처리한 다음 destroy() 메서드를 이용해 servlet을 제거(unload)한다.

 

요청 및 응답 처리

Container는 HttpServletRequest, HttpServletResponse 객체를 생성하고 이를 servlet의 service() 메서드에 전달을 한다. servlet은 이 객체를 사용해 클라이언트의 요청을 분석해서 응답을 만든다.

 

URL Mapping

Servlet Container는 클라이언트가 요청한 URL을 기반으로 호출할 servlet을 결정(mapping)한다. 즉, URL을 servlet과 연결하는 작업을 한다.

servlet을 특정한 URL에 매핑하는것뿐만 아니라 패턴을 이용해 servlet을 여러 URL에 매핑할수도 있다. 무슨말이냐면 servlet을 "/products/*" 에 매핑을하면 이 servlet은 "/products/" 로 시작하는 URL에 대한 모든 요청을 처리한다. 

 

멀티 스레딩 지원

클라이언트 요청에 대해서 Servlet Container는 새로운 Java 스레드를 생성하여 요청을 처리한다. 이러한 기능 덕분에 웹 애플리케이션은 여러 요청을 동시에 처리할 수 있다.

 

요청이 오면 Servlet Container는 새로운 스레드를 만들고, 스레드에서 servlet의 service() 메서드를 호출해 각 요청이 다른 요청과 독립적으로 처리되도록 한다. 즉 container가 여러 요청을 동시에 처리할 수 있게 한다.

 

 

 

매번 Spring boot를 이용해서 Servlet이나 Servlet Container가 자동으로 구성되었기 때문에 Servlet의 개념에 대해 잘 모르고 있었는데 이번 기회에 어떻게 작동하는지, 왜 필요한지에 대해 알 수 있어 좋았다.