본문 바로가기

Develop/Backend 가이드

[Spring] HTTP Request 를 처리하는 과정 - DispatcherServlet 원리

반응형

DispatcherServlet 원리
DispatcherServlet 원리

먼저 이 글은 Spring Web MVC 에 해당되며, Spring WebFlux 는 다른 글을 참고하시길 바랍니다.

HTTP Request 를 처리하는 과정 - DispatcherServlet 원리

Spring Web MVC 에서 HTTP Request 를 처리하는 핵심 클래스가 DispatcherServlet 이란 클래스입니다. DispatcherServlet 가 무엇인지 알아야 Spring Web MVC 서버가 어떻게 동작하는지를 알 수 있습니다. 클래스 이름 중 Servlet 단어가 클래스가 어떤 역할을 하는지 설명하는 핵심적인 단어입니다. 왜냐하면 Spring Web MVC 는 Servlet API (javax.servlet) 를 기반으로 만들어진 프레임워크이기 때문입니다.

Servlet

일반적으로 Servlet 이라 하면 네트워크 요청을 처리하기 위한 클래스를 의미합니다. 따라서 클래스에 Servlet 이라는 이름이 붙어 있으면, 네트워크 요청을 처리하기 위한 클래스 라고 할 수 있습니다. 요즘 웹 서버가 대부분이라, Servlet 이라 하면 HTTP 요청을 처리하는 클래스로 생각하셔도 무방합니다. Servlet 은 Servlet Container 에 의해 관리되며, Servlet Container 로는 Tomcat 이 대표적입니다.

DispatcherServlet

나머지 단어인 Dispatcher 는 단어 뜻 그대로 분류하여 전달한다는 의미입니다. 즉 DispatcherServlet 은 네트워크 요청을 받아 분배하는 역할을 하는 클래스입니다. Front Controller 디자인 패턴에 따라 Spring Web MVC 에서 DispatcherServlet 는 서버로 오는 모든 네트워크 요청을 받아서 분류하는 역할을 맡고 있습니다. DispatcherServlet 클래스가 네트워크 요청을 어떻게 처리할지는 당연히 개발자가 지정해줍니다.

HandlerMapping 원리

HandlerMapping은 일반적으로 HandlerMapping 을 상속하는 RequestMappingHandlerMapping 을 통해 설정합니다. 개발자가 아래와 같이 Controller 클래스 위에 @RequestMapping 을 표시하면 Spring 이@RequestMapping 을 확인하고 RequestMappingHandlerMapping 을 만들어 DispatcherServlet 에 등록합니다.

@RestController
@RequestMapping("/persons")
class PersonController {

    @GetMapping("/{id}")
    public Person getPerson(@PathVariable Long id) {
        // ...
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public void add(@RequestBody Person person) {
        // ...
    }
}

Controller 등록

@Controller
class MyController {

}

일반적으로 @Controller 를 표시하면 알아서 등록되지만 아래와 같이 등록할 수도 있습니다.

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("home");
    }
}
<mvc:view-controller path="/" view-name="home"/>

ViewResolver 역할

Spring Web MVC 에 여러 ViewResolver 가 기본으로 등록되어 있습니다. 특히 UrlBasedViewResolver가 적용되어 있어, Controller 메서드에서 반환할 때 redirect: 또는 forward: 를 포함할 수 있습니다. 그리고 Header, Cookie, Session, Locale 정보에 따라 알맞은 View 를 찾는 기능도 포함되어 있기 때문에 Client 상태에 따라 같으 정보로 다른 View 를 반환할 수도 있습니다.

새로운 ViewResolver 는 아래와 같이 등록하면 됩니다.

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        // ViewResolver 등록
    }
}
<mvc:view-resolvers>
    <!-- ViewResolver 등록 -->
</mvc:view-resolvers>

DispatcherServlet 를 자세하게 설정하는 방법

DispatcherServlet 생성에 직접적으로 개입하는 방법은 아래 2 가지 방법이 있습니다. 하지만 기본적으로 적용되는 설정만 사용해도 충분하므로 아래 방법을 굳이 사용할 필요는 없습니다.

첫번째 방법은 WebApplicationInitializer 를 구현하는 방법입니다.

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) {

        // WebApplicationContext 생성하고 설정
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(AppConfig.class);

        // DispatcherServlet 를 생성하고 등록
        DispatcherServlet servlet = new DispatcherServlet(context);
        ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
        registration.setLoadOnStartup(1);

        registration.addMapping("/app/*");
    }
}

두번째 방법은 web.xml 을 활용하는 방법입니다.

<web-app>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/app-context.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>

</web-app>

DispatcherServlet 구성에 개입하는 특별한 Bean 목록

DispatcherServlet 설정에 영향을 미치는 특별한 Bean 도 있습니다. 아래 클래스를 사용하게 되면 DispatcherServlet 가 네트워크 요청을 처리하는 과정에 변화를 줄 수 있습니다. 자세한 사항은 공식 문서를 참고해주세요.

반응형