1. 서블릿, 서블릿 컨테이너, Dispatch Servlet

서블릿

  • javax.servlet.Servlet 인터페이스의 구현체. 해당 인터페이스를 구현한 다음 web.xml 에 해당 구현체를 서블릿으로 등록하면, 서블릿 컨테이너가 이를 바탕으로 서블릿 객체를 생성하여 사용한다.
  • 서블릿 컨테이너는 서블릿 객체 각각을 한개씩 생성한다.

서블릿 컨테이너

  • 아파치톰캣이 서블릿 컨테이너에 해당된다.

 

서블릿 컨테이너의 역할

  • 웹 애플리케이션 서버 프로그램의 main 함수가 여기에 있을 것이다.
  • 서버 소켓을 생성하고 요청을 기다리다가, 클라이언트의 요청이 들어오면 새로운 thread 를 만든다.
  • 서블릿 객체 생성 등, 서블릿의 라이프사이클을 관리한다.

 

Dispatcher Servlet

  • spring-webmvc에서 제공하는 서블릿(=javax.servlet.Servlet 인터페이스의 구현체)

 

2. 스프링 MVC 프레임워크를 사용한 WAS 동작방식

 

그림 출처 : https://kouzie.github.io/spring/Spring-Spring-MVC/

 

1. 요청을 받은 서블릿 컨테이너는  해당 요청에 맞는 서블릿을 찾아서  서블릿의 service 메서드를 호출한다.

스프링 MVC 를 사용한 경우 Dispatcher Servlet 의 service 메서드를 호출할 것이다.

 

참고 : Servlet 인터페이스

public interface Servlet {

    public void init(ServletConfig config) throws ServletException;
    
    public ServletConfig getServletConfig();
    
    public void service(ServletRequest req, ServletResponse res)
	    throws ServletException, IOException;
        
    public String getServletInfo();
    
    public void destroy();
}

 

스프링 MVC 프레임워크를 사용한 웹 프로젝트의 산출물로 Gradle__sprringmvc_war 라는 war 파일이 나왔다고 해보자. 이것을 톰캣의 webapps 폴더 밑에 둔 뒤 톰캣 서버를 실행하면 톰캣 서버가 war 압축을 풀어서 사용한다고 한다.

(톰캣은 war파일이 webapps폴더에 있으면 자동으로 알아서 압축을 풀어 웹어플리케이션을 사용할 수 있게 한다고 함)

 

나는 이 작업을 직접 하지는 않았지만, 인텔리J가 대신 해줬다고 생각하면 타당한 듯 하다. 실제로 인텔리J에서 프로젝트를 실행한 뒤 톰캣의 폴더 구조를 보니 다음과 같았다.

프로젝트를 처음 실행했을 때 url이 localhost:8080/Gradle__springmvc_war/xxx가 되어서 당황했는데, war 파일 이름이 Gradle__springmvc_war 로 되어서 그런 것으로 보인다.

 

즉 나의 경우, 

/Gradle__springmvc_war 로 시작하는 요청이 왔을 때 서블릿 컨테이너가 Dispatcher Servlet 인스턴스의 service 메서드를 호출한 것이다.

 

이제부터는 DispatcherServlet#service() 가 실행되는 과정이다. 

 

2. Dispatcher Servlet은 HandlerMapping 이라는 객체에게 컨트롤러 검색을 요청한다.

정확히 말하면 HandlerMapping 은 컨트롤러를 검색하는 것이 아니라 Handler를 검색하는 것이고, 컨트롤러는 Handler 중 하나라고 할 수 있다.

스프링MVC의 HandlerMapping 에는 다음 네가지 종류가 있다.

  • BeanNameHandlerMapping : Bean 이름과 URL 을 매핑시켜준다.
  • ControllerClassNameHandlerMapping
  • SimpleHandlerMapping
  • RequestMappingHandlerMapping

 

이 중에서 @Controller 어노테이션이 붙은 객체를 Handler 로 사용하는 방식은 RequestMappingHandlerMapping

이다. 만약 이 방식을 사용할거라면 RequestMappingHandlerMapping을 설정파일에서 Bean으로 등록해줘야 한다.

 

그런데 설정파일에 @EnableWebMvc 어노테이션을 사용하면 이 코드를 작성하지 않아도 된다.

@EnableWebMvc 어노테이션을 사용하면 매우 많은 스프링 빈을 추가해준다. 이 중에는

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping 도 있다.

 

3. DispatcherServlet 은 HandlerMapping이 찾아준 컨트롤러 객체를 처리할 수 있는 HandlerAdapter  bean에게 요청 처리를 위임한다.

HandlerAdapter는 컨트롤러의 알맞은 메서드를 호출해서 요청을 처리하고, 그 결과를 ModelAndView 객체로서 DispatcherServlet에 리턴한다.

근데 Rest Controller 도 결국은 ModelAndView 객체로 리턴하게 되는걸가..? 궁금

 

4. DispatcherServlet은 ModelAndView의 정보를 ViewResolver bean객체에게 넘기면서 View 객체를 요청한다.

만약 웹 프로젝트가 아래와 같은 설정파일을 사용했다고 하자.

package config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {

	@Override
	public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
		configurer.enable();
	}

	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		registry.jsp("/WEB-INF/view/", ".jsp");
	}
}

 

 

위 설정은 org.springframework.web.servlet.view.InternalResourceViewResolver 클래스를 이용해서 다음 설정과 같은 빈을 등록한다.

@Bean
public ViewResolver viewResolver() {
    InternalResourceViewResolver vr = new InternalResourceViewResolver();
    vr.setPrefix("/WEB-INF/view/");
    vr.setSuffix(".jsp");
    return vr;
}

 

이 ViewResolver (InternalResourceViewResolver) 는

뷰 이름이 "hello" 라면 "/WEB-INF/view/hello.jsp" 경로를 뷰 코드로 사용하는 View (InternalResourceView) 객체를 리턴한다.

 

5. DispatcherServlet은 ViewResolver로부터 얻은 View 객체에게 응답 생성을 요청하고, 그 리턴값으로 브라우저에게 응답한다.

 


출처

초보 웹 개발자를 위한 스프링 5 프로그래밍 입문 chapter 10

서블릿 guruble.com/about-servlet/

Servlet Container 역할 workatit.tistory.com/19

Servlet & Spring Web MVC www.youtube.com/watch?v=2pBsXI01J6M

Tomcan & .war 파일 withcoding.com/38

서블릿 이름 gmlwjd9405.github.io/2018/10/29/web-application-structure.html

+ Recent posts