ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [스프링MVC - 1편] 스프링 MVC 전체 구조
    스프링&스프링부트 2025. 1. 27. 13:15
    SpringMVC 구조

     

     

     

    DispatcherServlet 구조 살펴보기

    - org.springframework.web.servlet.DispatcherServlet

    스프링 MVC도 프론트 컨트롤러 패턴으로 구현되어 있다

    스프링 MVC의 프론트 컨트롤러가 바로 디스패처 서블릿(DispatcherServlet)이다

    그리고 디스패처 서블릿이 바로 스프링 MVC 핵심이다

     

     

     

    요청 흐름

    서블릿이 호출되면 HttpServlet 제공하는 service() 호출된다

    스프링 MVC DispatcherServlet 부모인 FrameworkServlet에서 service() 오버라이드 두었다

    FrameworkServlet.service()` 시작으로 여러 메서드가 호출되면서 DispatcherServlet.doDispatch() 호출된다

     

     

     

    동작 순서

    1. 핸들러 조회 : 핸들러 매핑을 통해 요청 URL 매핑된 핸들러(컨트롤러)를 조회한다

    2. 핸들러 어댑터 조회 : 핸들러를 실행할  있는 핸들러 어댑터를 조회한다

    3. 핸들러 어댑터 실행 : 핸들러 어댑터를 실행한다

    4. 핸들러 실행 : 핸들러 어댑터가 실제 핸들러를 실행한다

    5. ModelAndView 반환 : 핸들러 어댑터는 핸들러가 반환하는 정보를 ModelAndView변환해서 반환한다

    6. viewResolver 호출 : 뷰 리졸버를 찾고 실행한다

    7. View 반환 : 뷰 리졸버는 뷰의 논리 이름을 물리 이름으로 바꾸고, 렌더링 역할을 담당하는  객체를 반환한다

    8. 렌더링 : 뷰를 통해서 뷰를 렌더링 한다

     

     

     

    주요 인터페이스 목록
    • 핸들러 매핑: org.springframework.web.servlet.HandlerMapping
    • 핸들러 어댑터: org.springframework.web.servlet.HandlerAdapter
    •  리졸버: org.springframework.web.servlet.ViewResolver
    • org.springframework.web.servlet.View

     

     

    핸들러 매핑과 핸들러 어댑터

    1. OldController

    @Component("/springmvc/old-controller")
    public class OldController implements Controller {
        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            System.out.println("OldController.handleRequest");
            return null;
        }
    }
    • @Component : 이 컨트롤러는 /springmvc/old-controller 라는 이름의 스프링 빈으로 등록되었다
    • 빈의 이름으로 URL을 매핑한다

     

     

     

    old-controller 호출에 필요한 2가지

    • HandlerMapping(핸들러 매핑)
      • 핸들러 매핑에서  컨트롤러를 찾을  있어야 한다
      • 예) 스프링 빈의 이름으로 핸들러를 찾을  있는 핸들러 매핑이 필요하다
    • HandlerAdapter(핸들러 어댑터)
      • 핸들러 매핑을 통해서 찾은 핸들러를 실행할  있는 핸들러 어댑터가 필요하다
      • ) Controller인터페이스를 실행할  있는 핸들러 어댑터를 찾고 실행해야 한다

     

     

     

    old-controller 어떻게 호출될 있을까

    1. 핸들러 매핑으로 핸들러 조회

        1. HandlerMapping을 순서대로 실행해서 핸들러를 찾는다

        2. 경우 이름으로 핸들러를 찾아야 하기 때문에 이름 그대로 이름으로 핸들러를 찾아주는

            BeanNameUrlHandlerMapping 실행에 성공하고 핸들러인 OldController 반환한다

    2. 핸들러 어댑터 조회

        1. HandlerAdapter supports() 순서대로 호출한다

        2. SimpleControllerHandlerAdapter Controller 인터페이스를 지원하므로 대상이 된다

    3. 핸들러 어댑터 실행

        1. 디스패처 서블릿이 조회한 SimpleControllerHandlerAdapter 를 실행하면서 핸들러 정보도 함께 넘겨준다

        2. SimpleControllerHandlerAdapter는 핸들러인 OldController를 내부에서 실행하고 그 결과를 반환한다

     

     

    2. HttpRequestHandler

    @Component("/springmvc/request-handler")
    public class MyHttpRequestHandler implements HttpRequestHandler {
        @Override
        public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("MyHttpRequestHandler.handleRequest");
        }
    }

     

     

     

     

    my-http-request-handler 어떻게 호출될  있을까

    1. 핸들러 매핑으로 핸들러 조회

        1. HandlerMapping을 순서대로 실행해서, 핸들러를 찾는다

        2. 경우 이름으로 핸들러를 찾아야 하기 때문에 이름 그대로 이름으로 핸들러를 찾아주는

            BeanNameUrlHandlerMapping 실행에 성공하고 핸들러인 MyHttpRequestHandler 반환한다

    2. 핸들러 어댑터 조회

        1.  HandlerAdapter supports() 순서대로 호출한다

        2. HttpRequestHandlerAdapter HttpRequestHandler 인터페이스를 지원하므로 대상이 된다

    3. 핸들러 어댑터 실행

        1. 디스패처 서블릿이 조회한 HttpRequestHandlerAdapter를 실행하면서 핸들러 정보도 함께 넘겨준다

        2. HttpRequestHandlerAdapter 핸들러인 MyHttpRequestHandler 내부에서 실행하고,

           그 결과를 반환한다

     

     

     

    뷰 리졸버
    @Component("/springmvc/old-controller")
    public class OldController implements Controller {
        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            System.out.println("OldController.handleRequest");
            return new ModelAndView("new-form");
        }
    }
    spring.application.name=servlet
    logging.level.org.apache.coyote.http11=trace
    
    spring.mvc.view.prefix=/WEB-INF/views/
    spring.mvc.view.suffix=.jsp

     

     

    리졸버 - InternalResourceViewResolver

    스프링 부트는 InternalResourceViewResolver라는 리졸버를 자동으로 등록하는데, 이때 application.properties 등록한 spring.mvc.view.prefix, spring.mvc.view.suffix 설정 보를 사용해서 등록한다

     

     

     

    리졸버 동작 방식

    1. 핸들러 어댑터 호출

        핸들러 어댑터를 통해 new-form이라는 논리 이름을 획득한다

    2. ViewResolver 호출

        new-form이라는 이름으로 viewResolver 순서대로 호출한다

        BeanNameViewResolver new-form이라는 이름의 스프링 빈으로 등록된 뷰를 찾아야 하는데 없다

        > InternalResourceViewResolver 호출된다

    3. InternalResourceViewResolver

        이 리졸버는 InternalResourceView 반환한다

    4. - InternalResourceView

        InternalResourceView JSP처럼 포워드 forward() 호출해서 처리할 있는 경우에 사용한다

    5. view.render()

        view.render() 호출되고 InternalResourceView forward() 사용해서 JSP 실행한다

    728x90
Designed by Tistory.