본문 바로가기
Backend, Server/Spring MVC

[Spring MVC] 스프링 MVC 구조, 핸들러 매핑, 핸들러 어댑터, 뷰 리졸버

by ggyongi 2022. 1. 18.
반응형

Dispatcher Servlet이 스프링 MVC 구조의 핵심이 된다.

 

 

<Dispatcher Servlet 코드 구성>     (**직접 만든 servlet MVC구조 코드로 복습하면 이해가 잘 됨)

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

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

* 어댑터가 필요한 이유? 확장성있는 설계를 위해 => 각기 다른 핸들러(컨트롤러)가 유연하게 동작되게 하려면 어댑터가 끼워져야 함

3. 핸들러 어댑터 실행

4. 핸들러 실행 : 핸들러 어탭터가 핸들러를 실행

5. ModelAndView 반환 : 핸들러 어댑터는 핸들러가 반환하는 정보를 MAV로 변환하여 반환

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

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

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

 

 

스프링 MVC의 강점

-핸들러 매핑, 핸들러 어댑터, 뷰 리졸버, 뷰를 모두 인터페이스로 제공하여 확장성 있는 설계를 제공

 

 

 

핸들러 매핑

 

초기 방식

@Component : "/springmvc/old-controller"이라는 이름의 스프링 빈이 등록되고, 이 빈으로 URL 매핑

@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");
    }
}

 

<예시>

Servlet과 가장 유사한 형태인 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");
    }
}

 

스프링에는 이미 HandlerMapping과 HandlerAdapter가 대부분 구현되어 있다.

스프링은 아래와 같은 순서로 핸들러 매핑, 핸들러 어댑터 조회를 실행한다.

<HandlerMapping>
0 = RequestMappingHandlerMapping : 애노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
1 = BeanNameUrlHandlerMapping : 스프링 빈의 이름으로 핸들러를 찾는다.

<HandlerAdapter>
0 = RequestMappingHandlerAdapter : 애노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
1 = HttpRequestHandlerAdapter : HttpRequestHandler 처리
2 = SimpleControllerHandlerAdapter : Controller 인터페이스(애노테이션X, 과거에 사용) 처리

 

 

과정

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

: 여기서는 빈 이름으로 핸들러를 찾음. BeanNameUrlHandlerMapping이 실행되고

MyHttpRequestHandler가 반환됨

 

2. 핸들러 어댑터 조회

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

 

3. 핸들러 어댑터 실행

HttpRequestHandlerAdapter가 핸들러인 MyHttpRequestHandler를 내부에서 실행하고 그 결과를 반환해줌

 

 

* @RequestMapping

위에서 알 수 있듯이 우선순위가 가장 높은 핸들러 매핑과 핸들러 어댑터는 

RequestMappingHandlerMapping, RequestMappingHandlerAdapter 이다.

이 방식이 실무에서는 99.99% 사용됨

 

 

 

뷰 리졸버 이용하기

스프링 부트는 InternalResourceViewResolver 라는 뷰 리졸버를 자동으로 등록하는데,

application.properties에 다음을 추가하면

spring.mvc.view.prefix=/WEB-INF/views/

spring.mvc.view.suffix=.jsp

상대 경로만을 이용해서 사용할 수 있다.

 

 

스프링 부트가 자동 등록하는 뷰 리졸버

1 = BeanNameViewResolver : 빈 이름으로 뷰를 찾아서 반환한다. (예: 엑셀 파일 생성 기능에 사용)

2 = InternalResourceViewResolver : JSP를 처리할 수 있는 뷰를 반환한다

 

 

뷰 리졸버 작동 방식

@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");
    }
}

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를 실행한다.

 

 

---------------

참고: 인프런 김영한님 강의(스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술)

 

비전공자 네카라 신입 취업 노하우

시행착오 끝에 얻어낸 취업 노하우가 모두 담긴 전자책!

kmong.com

댓글