기록하자..
Spring의 웹 요청 처리 개발 (Servlet, DispatcherServlet) 본문
Spring을 통해 웹 요청 처리를 하게 되면 사용자에게 동적인 웹페이지를 제공한다. 이는 Spring이 Servlet을 이용해 웹 요청을 처리한다는 것이다. Spring으로 웹 요청 처리를 하게 되면 SpringMVC의 DispatcherServlet을 사용하고 웹 요청 처리와 관련된 Spring 빈들의 주입을 받아서 요청을 처리하게 된다. 웹 요청 처리 과정을 알기 위해 먼저 Servlet에 대해 간단히 알아보자.
Servlet
먼저 Servlet의 사전적의미는 다음과 같다.
Servlet은 자바를 사용하여 웹페이지를 동적으로 생성하는 서버 측 프로그램 혹은 그 사양을 말한다.
(뭔가 머리로 이해하기 힘들다..) 이해하기 쉽게 설명하기 위해, 먼저 HTTP 요청을 가져와보자. 밑의 그림은 Tecoble 블로그에서 가져온 HTTP request, response에 대한 그림이다.

위의 요청이 서버로 들어온다고 하면 개발자들은 위의 텍스트들을 직접 해석하고 텍스트 형식의 응답을 만들어야 한다면 모든 규약을 확인하고 규약에 맞는 처리를 하고, 처리한 값을 응답으로 생성해야 한다. (할 일이 굉장히 많아진다.)
하지만 Servlet이 요구하는 구현 규칙을 지켜가며 Servlet을 정의하면 우리는 HTTP 요청정보를 쉽게 사용하며 처리 결과 또한 쉽게 담을 수 있다. 개발자는 서블릿이 처리해야 하는 비즈니스 로직에 집중할 수 있게 되는 것이다.
임의의 서블릿을 생성해 보았다.

서블릿이 생성이 되면 init 메서드가 호출이 되고, 서비스 요청이 오면 service 메서드가 호출이 되고, 서블릿이 소멸이 되면 destroy 메서드가 호출이 될 것이다.
우리가 집중해야할 부분은 service 메서드인데, 요청이 오게 되면 req의 정보를 읽어 HTTP 메서드의 정보를 확인하고 그에 따른 메서드 호출을 나누면 된다. 코드로 살펴보자면 다음과 같다.

결국 우리는 HTTP 메서드에 따라 doXXX 메서드를 호출해 주면 되는 것이다.
그런데 우리는 이 service() 메서드가 어떻게 호출되는지 알아야 한다. 그러기 위해서 ServletContainer에 대해서 알아보자.
ServletContainer
서블릿 컨테이너는 서블릿의 생명주기를 관리하는 역할을 한다.

- 브라우저가 http 요청을 보내게 되면 WAS는 http 요청 메시지를 기반으로 ServletRequest와 ServletResponse 객체를 생성하게 된다.
- 요청이 들어온 URL에 매핑할 서블릿을 설정 파일을 통해 탐색한다.
- 해당 서블릿이 존재하지 않으면 init 메서드를 호출해 서블릿을 생성하게 된다.
- 서블릿 컨테이너에 스레드를 생성하고 service 메서드를 호출하게 된다.
- 처리가 끝나면 응답 결과를 HttpServletResponse에 담아 보낸다.
- 응답 후 HttpServletRequest와 HttpServletResponse 객체를 소멸시킨다.
매핑할 서블릿을 찾는 설정파일은 다음과 같다.

스프링 공식문서에서 가져온 그림인데, <servlet-mapping>이라는 태그 아래에 <url-pattern>에 일치하는 url 요청이 들어오면 app1이라는 서블릿을 호출하겠다는 것이다. 그리고 app1이라는 서블릿은 org.springframework.web.servlet.DispatcherServlet으로 정의가 되어있다는 것이다.
그런데, 마지막에 보면 HttpServletRequest와 HttpServletResponse 객체는 소멸시키지만 서블릿은 소멸시키지 않고 있다. 이는 서블릿이 싱글톤으로 관리가 되어서 그렇다. 서블릿은 소멸이 되지 않고 컨테이너 안에 있다가 다음번에 같은 요청이 오게 되면 서블릿 컨테이너에 의해서 다시 호출되서 사용되는 것이다.
다시 처음으로 돌아가서.. 결국 서블릿 컨테이너는 서블릿의 생명주기를 관리해주는 역할을 한다.
그래서 서블릿 컨테이너의 특징에 대해 정리를 하자면..
- 서블릿 객체의 생명주기를 관리
- 서블릿 객체는 싱글톤으로 관리
- 동시 요청을 위한 멀티스레드를 지원
(동시 요청은?) 그러면 한 서블릿이 요청을 처리하고 있는 와중에 다른 요청이 들어오게 되면 어떻게 될까?
이때는 멀티스레드로 처리를 하게 되는데, 서블릿 컨테이너에 여러 스레드가 생성이 되어서 스레드 당 다른 서블릿이 혹은 여러 스레드에서 한 서블릿의 요청을 처리할 수 있게 된다.
하지만 스레드를 생성하는 것은 비용이 크고 스레드를 계속해서 생성하다가 하드웨어의 수용력(?)을 넘어가게 되면은 서버가 터져버린다. 또한 한 스레드에서 다른 스레드로 넘어가는 Context Switching은 오버헤드를 일으키기 때문에 신경써야할 부분이 많다.
그래서 이런 요청당 서블릿을 정의하는 것은 굉장히 비효율적인 부분이 있다. 그래서 Spring은 DispatcherServlet을 사용하게 된다.
DispatcherServlet
SpringMVC는 프런트컨트롤러 패턴을 통해 중앙에 Servlet을 두었는데, 이게 DispatcherServlet이다. 클라이언트가 보내는 모든 요청은 DispatcherServlet으로 가게 되고 DispatcherServlet에서 url에 맞는 핸들러를 호출하게 되는 것이다.

- HTTP 요청이 오면 DispatcherServlet이 해당 요청을 처리할 수 있는 핸들러를 조회한다.
- 이후 핸들러를 처리할 수 있는 핸들러 어댑터를 조회한다.
- DispatcherServlet이 어댑터의 handle 메서드를 호출하게 된다.
- 위에서 조회한 핸들러의 메서드를 호출해서 처리 로직을 수행하게 된다.
- 그리고 그 처리결과를 ModelView 객체로 변환해서 DispatcherServlet이 받는다.
- DispatcherServlet은 반환받은 ModelView 객체를 viewResolver를 호출하며 넘긴다.
- DispatcherServlet은 View를 반환받는다.
- 마지막으로 반환받은 View를 이용해 JSP나 Thymeleaf 같은 템플릿 엔진을 이용해 응답을 하게 된다.
결론
그런데, 우리가 개발하면서 핸들러를 조회하고, 핸들러를 처리할 수 있는 어댑터를 조회하는 등의 과정은 딱히 신경 쓰지 않았다. 우리가 집중해야 하는 것은 핸들러(컨트롤러)를 구현하는 것이다. 그러면 나머지 과정은 누가 해주는 것일까?
그 과정은 DispatcherServlet이 스프링컨테이너로부터 객체들을 주입받아서 처리하게 된다.
스프링 공식문서에 보면 다음과 같은 그림이 있다.

위의 HTTP 요청을 처리하는 과정에서 DispatcherServlet은 스프링 컨테이너로부터 필요한 빈을 주입받아 사용하게 되는 것이다. 웹과 관련된 빈들은 Servlet WebApplicationContext에서, 웹 이외의 것들은 Root WebApplicationContext로부터 주입을 받아 요청을 처리하게 된다.
DispatcherServlet의 요청처리과정 뿐만 아니라 Controller에서 Root WebApplicationContext, ServletConatiner를 사용해 Service를 호출하는 등의 적절한 처리를 할 수 있게 되는 것이다.
다시 처음으로 돌아가서 Spring으로 웹 요청을 처리하는 것은 DispatcherServlet을 사용하고 스프링 컨테이너를 사용해 처리과정에서 필요한 빈들을 주입받아(IoC) 개발할 수 있다는 의미가 된다. 즉, 우리는 핸들러(컨트롤러)에 집중해서 개발을 할 수 있게 된다.
참고 자료
https://tecoble.techcourse.co.kr/post/2021-05-23-servlet-servletcontainer/
Servlet 과 ServletContainer
Servlet 서블릿(Servlet…
tecoble.techcourse.co.kr
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#spring-web
Web on Servlet Stack
Spring Web MVC is the original web framework built on the Servlet API and has been included in the Spring Framework from the very beginning. The formal name, “Spring Web MVC,” comes from the name of its source module (spring-webmvc), but it is more com
docs.spring.io
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의
웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -
www.inflearn.com