작심구일러의 스프링 시작하기(9)

서은경·2022년 8월 23일
0

Spring

목록 보기
15/43

스프링 MVC 핵심 구성 요소

스프링 MVC의 핵심 구성 요소는 DispatcherServlet을 중심으로 이루어져 있다고 볼 수 있다!

이전 포스팅에서 설명했지만 다시 한번 짚고 넘어가자면 DispatcherServlet은 Front-Controller 라고 보면 된다 모든 요청이 첫번째로 맞닥뜨리는 컨트롤러이다.

크게 9가지 순서로 나눠서 설명해보면

  1. 웹브라우저 -> DispatcherServlet
    요청 전송
    :: 웹 브라우저로부터 요청이 들어온다.
  2. DispatcherServlet -> HandlerMapping
    요청 URL과 매칭되는 컨트롤러 검색 요청
    :: HandlerMapping이라는 빈 객체에 컨트롤러 검색을 요청하면, HandlerMapping은 클라이언트의 요청을 이용해 이를 처리할 컨트롤러 빈 객체를 DispatcherServlet에 전달한다.
    예를 들어 웹 요청경로가 '/hello' 라면 등록된 컨트롤러 빈 중에서 '/hello' 요청 경로를 처리할 컨트롤러를 리턴한다.
  3. DispatcherServlet -> HandlerAdapter
    컨트롤러 처리 요청
    :: DispatcherServlet은 HandlerMapping이 찾아준 컨트롤러 객체를 처리할 수 있는 HandlerAdapter 빈에게 요청처리를 위임한다.
    HandlerAdapter 빈은 DispatcherServlet이 @Controller, Controller 인터페이스, HttpRequestHandler 인터페이스를 동일한 방식으로 처리할 수 있도록 해준다.
  4. HandlerAdapter -> Controller
    실행
    :: HandlerAdapter는 컨트롤러의 알맞은 메서드를 호출해서 요청을 처리하고
  5. Controller -> HandlerAdapter
    결과 리턴
    :: 해당 결과를 리턴 받은 뒤
  6. HandlerAdapter -> DispatcherServlet
    컨트롤러 실행결과를 ModelAndView로 변환하여 리턴
    :: ModelAndView라는 객체로 변환하여 다시 DispatcherServlet에 리턴한다.
  7. DispatcherServlet -> ViewResolver
    컨트롤러의 실행 결과를 보여줄 VIew 검색
    :: 결과를 보여줄 뷰를 찾기 위해 ViewResolver 빈 객체를 사용한다. ModelAndView는 컨트롤러가 리턴한 뷰 이름을 담고 있는데 ViewResolver는 이 뷰 이름에 해당하는 View 객체를 찾거나 생성해서 리턴한다.
  8. DispatcherServlet -> View
    응답 생성 요청
    :: ViewResolver가 리턴한 View 객체에게 응답 결과 생성을 요청한다.
  9. View -> JSP
    응답 생성
    :: View 객체는 JSP를 실행함으로써 웹 브라우저에 전송할 응답결과를 생성한다.

컨트롤러와 핸들러

스프링 MVC는 웹 요청을 처리할 수 있는 범용 프레임워크이다. 클라이언트 요청을 처리하는 객체의 타입이 @Controller일 수도, 자신이 직접 만든 클래스 일수도, HttpRequestHandler일 수도 있기 때문에 스프링 MVC는 웹 요청을 실제로 처리하는 객체를 Handler라고 표현한다.

따라서 특정 요청 경로를 처리해주는 핸들러를 찾아주는 객체를 HandlerMapping 이라고 부른다.

DispatcherServlet은 핸들러 객체의 실제 타입에 상관없이 실행결과를 ModelAndView라는 타입으로만 받을 수 있으면 된다. 하지만 핸들러의 실제 구현 타입에 따라 그렇지 않은 객체가 있는데 이 실행 결과를 ModelAndView로 변환해주는 객체가 HandlerAdapter이다.

DispatcherServlet과 스프링 컨테이너

	<servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>
                org.springframework.web.context.support.AnnotationConfigWebApplicationContext
            </param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                config.MvcConfig
                config.ControllerConfig
            </param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

DispatcherServlet은 전달받은 설정파일을 이용해 스프링 컨테이너를 생성하는데, HandlerMapping,HandlerAdapter,Controller,ViewResolver 등의 빈은 DispatcherServlet이 생성한 스프링 컨테이너에서 구한다.

@Controller를 위한 HandlerMapping과 HandlerAdapter

// 스프링 MVC 설정을 활성화한다. 스프링 MVC를 사용하는데 필요한 다양한 설정을 생성한다.
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {

이 설정은 매우 다양한 스프링 빈 설정을 추가해준다. 이 태그가 빈으로 추가해주는 클래스 중에는 @Controller 타입의 핸들러 객체를 처리하기 위한 다음의 두 클래스도 포함되어 있다.

  • org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
    : @Controller 어노테이션이 적용된 객체의 요청 매핑 어노테이션(@GetMapping) 값을 이용해 웹 브라우저의 요청을 처리할 컨트롤러 빈을 찾는다.
  • org.springframework.web.servlet.mvc.method.anntation.RequestMappingHandlerAdapter
    : 컨트롤러의 메서드를 알맞게 실행하고 그 결과를 ModelAndView 객체로 변환해서 DispatcherServlet에 리턴한다.

직접 설정 예

package config;

// 스프링 MVC 프레임워크 동작 방식
// 직접 설정 예

import org.springframework.context.annotation.Bean;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import java.util.HashMap;
import java.util.Map;

// @Configuration
public class MvcConfigEx {

    @Bean
    public HandlerMapping handlerMapping() {
        RequestMappingHandlerMapping hm = new RequestMappingHandlerMapping();
        hm.setOrder(0);
        return hm;
    }

    @Bean
    public HandlerAdapter handlerAdapter() {
        RequestMappingHandlerAdapter ha = new RequestMappingHandlerAdapter();
        return ha;
    }

    @Bean
    public HandlerMapping simpleHandlerMapping() {
        SimpleUrlHandlerMapping hm = new SimpleUrlHandlerMapping();
        Map<String, Object> pathMap = new HashMap<>();
        pathMap.put("/**", defaultServletHandler());
        hm.setUrlMap(pathMap);
        return hm;
    }

    @Bean
    public HttpRequestHandler defaultServletHandler() {
        DefaultServletHttpRequestHandler handler = new DefaultServletHttpRequestHandler();
        return handler;
    }

    @Bean
    public HandlerAdapter requestHandlerAdapter() {
        HttpRequestHandlerAdapter ha = new HttpRequestHandlerAdapter();
        return ha;
    }

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

@EnableWebMvc 어노테이션을 사용하지 않고 스프링 MVC를 사용하려면 설정파일을 이렇게 수정해주면 된다.

🖐 정리하자면,
DispatcherServlet은 웹 브라우저의 요청을 받기 위한 창구 역할을 하고, 다른 주요 구성 요소들을 이용해서 요청 흐름을 제어하는 역할을 한다.
HandlerMapping은 클라이언트의 요청을 처리할 핸들러 객체를 찾아준다. 핸들러(커맨드) 객체는 클라이언트의 요청을 실제로 처리한 뒤 뷰 정보와 모델을 설정한다.
HandlerAdapter는 DispatcherServlet과 핸들러 객체 사이의 변환을 알맞게 처리해준다.
ViewResolver는 요청 처리 결과를 생성할 View를 찾아주고
View는 최종적으로 클라이언트에 응답을 생성해서 전달한다.

0개의 댓글