Spring

Servlet Container란? 그리고 Spring과의 관계

천방지축 개발노트 2024. 9. 17. 02:14
Servlet과 Servlet Container

Servlet은 URI정보 및 클라이언트의 요청 정보를 분석하는 기능을 담당하는 Java 표준 기술이다. 그리고 이 표준 기술을 이용한 Servlet Container 중 가장 대표적인 예로 Tomcat이 있다. 다시 말해, 우리가 많이 사용하는 Tomcat이라는 WAS는 (Servlet) Container 기술을 구현한 라이브러리 중의 하나이며, Tomcat 자체가 Java의 표준이 아니다. 이외에도 종류가 많은데 특히 Springboot에서는 Tomcat 과 Jetty, undertow(언더토우) 이 3가지의 Container를 Standalone하게 동작할 수 있도록 지원하고 있다(쉽게 변경 및 선택이 가능하다)

 

Spring Boot Reference Documentation

This section goes into more detail about how you should use Spring Boot. It covers topics such as build systems, auto-configuration, and how to run your applications. We also cover some Spring Boot best practices. Although there is nothing particularly spe

docs.spring.io

※ Standalone : '독립적이다'란 단어로 '혼자서 동작할 수 있다'를 의미하는데, 다른 소프트웨어나 외부 서비스의 지원 없이 독립적으로 실행할 수 있는 애플리케이션을 말한다(Springboot의 톰캣을 예로 들자면 애플리케이션 자체에 내장돼있어 별도의 설치 없이 실행할 수 있다는 의미)

 

 

Servlet Container과 Spring Container

이전 글에서 컨테이너란 무언가를 담아 관리하는 공간이라고 했었다. 마찬가지로 Servlet Container란 특정 기능(회원가입 등)의 처리를 담당하는 Web Component(Java에서는 Servlet)들의 라이프사이클을 관리한다. Client Request(웹 요청)가 왔을 때, 이 Servlet Container가 어떤 Servlet(Web Component)에게 처리를 위임할지 결정하는 Routing 역할까지 수행한다.

public static void main(String[] args) {
// ServletWebServerFactory: 서블릿 컨테이너의 종류에 종속되지 않도록 추상화한 인터페이스
ServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
WebServer webServer = serverFactory.getWebServer(servletContext -> {
    // 생성한 서블릿 컨테이너에 서블릿을 추가
    servletContext.addServlet("Front Controller", new HttpServlet() {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ... {
            if (req.getRequestURI().equals("/hello") {
                System.out.println("hello URI로 매핑");
                if(req.getMethod().equals(HttpMethod.GET.name())) {
                    ...
                }
                ...
            }
            else if (req.getRequestURI().equals("/user")) {
                System.out.println("user URI로 매핑");
                ...
                resp.setStatus(HttpStatus.OK.value());
                resp.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE);
            }
            else {
                resp.setStatus(HttpStatus.NOT_FOUND.value()); //404
            }
        }
    }).addMapping("/hello"); // URL 매핑
});
webServer.start();
}

 

Servlet을 계속 추가하는 방식을 이용하면 애플리케이션 입장에선 각각의 요청마다 웹 요청/응답을 위해 Request/Response Object를 매번 다뤄야 하는 방식이기 때문에 한계가 있다. 그래서 위 예제 코드와 같이 Servlet에 공통적으로 있는 코드를 중앙화하여 전, 후처리를 하는 개념인 'Front Controller'를 만드는 방식이 등장했다. 궁극적으로 Spring에서는 이 Front Controller와 같은 기능을 수행하는 'DispatcherServlet'이라는 서블릿 클래스가 존재한다. 이 오브젝트 덕분에 우리는 일일이 Request 정보를 분석하고 바인딩하는 코드를 작성하지 않아도 되는 것이다.

Servlet Container와 Spring Container

위 그림과 같이 Servlet Container를 통해서 Spring Container가 호출되며, 구체적으로 DispatcherServlet은 Spring Container에서 Controller에 값을 바인딩하거나 결과를 받아서 웹 응답 Object를 생성한다. 웹 요청을 처리하기 위해서는 Servlet Container가 반드시 필요하며, 이름이 비슷하다고 해서 뭔가 Servlet Container를 아예 대체하는 기술로 Spring Container라는 게 있는 것이 아니다. 즉, 기본적으로 자바의 웹 표준 기술을 사용하려면 Servlet Container가 필요하다.