스프링 MVC

무삭이의 개발일지·2023년 3월 17일
0

DispatcherServlet에 대해 알아보자.

DispatcherServlet
스프링 MVC의 핵심은 바로 디스패처 서블릿!!!
DispatcherServlet은 스프링 웹 애플리케이션에서 공통적으로 적용되는 주요 역할들을 처리하는데 사용된다. 즉, 공통 정책을 처리하는 곳.
DispatcherServlet은 공항과 같다. DispatcherServlet도 servlet답게 HttpServlet을 상속 받아서 사용한다. 그림과 같이(DispatcherServlet -> FrameworkServlet -> HttpServletBean ->HttpServlet). 스프링 부트는 DispatcherServlet을 서블릿으로 자동으로 등록하면서 모든 경로(urlPatterns="/")에 대해서 매핑한다. 서블릿이 호출되면 서블릿 존재 여부에 따라 존재한다면 존재하는 서블릿을 가지고 사용하지만 존재하지 않다면 생성을 하고 init()메서드를 통해 초기화를 시키고 이후 서블릿 컨테이너는 요청에 대한 service()메서드를 호출한다. 여기서 service()메서드는 HttpServlet의 service()메서드를 오버라이드한 FrameworkServlet의 service()메서드가 호출된다. 이 때 FrameworkServlet의 service() 메서드는 요청을 처리하고, DispatcherServlet의 doDispatch() 메서드가 호출된다. doDispatch()메서드는 핸들러조회부터 뷰 렌더링까지 처리를 담당하며, 최종적으로 응답이 생성되어 클라이언트에게 전송한다.

SpringMVC 구조

동작 순서
1. 핸들러 조회 : 핸들러 매핑을 통해 요청 URL에 매핑된 핸들러(컨트롤러)를 조회한다.
2. 핸들러 어댑터 조회 : 핸들러를 실행할 수 있는 핸들러 어댑터를 조회한다.
3. 핸들러 어댑터 실행 : 핸들러 어댑터를 실행한다.
4. 핸들러 실행 : 핸들러 어댑터가 실제 핸들러를 실행한다.
5. ModelAndView 반환 : 핸들러 어댑터는 핸들러가 반환하는 정보를 ModelAndView로 반환해서 반환
6. viewResolver 호출 : 뷰 리졸버를 찾고 실행한다.
7. View 반환 : 뷰 리졸버는 뷰의 논리 이름을 물리 이름으로 바꾸고, 렌더링 역할을 담당하는 뷰 객체를 반환한다.
8. 뷰 렌더링 : 뷰를 통해서 뷰를 렌더링 한다.

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

핸들러 매핑과 핸들러 어댑터는 어떻게 사용될까?

@Component를 받은 컨트롤러가 하나 있다고 생각해보자..!!
@Component(/url) /url이라는 이름의 스프링 빈이 등록되었다. 빈의 이름으로 url을 매핑할 것이다.

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

스프링 이미 필요한 핸들러 매핑과 핸들러 어댑터를 구현해놨기 때문에 우리는 그저 사용만 하면 된다ㅋ

그래서 스프링 부트는 자동으로 핸들러 매핑과 핸들러 어댑터를 등록한다. 하지만 조건이 있는데..

HandlerMapping

0순위는 RequestMappingHandlerMapping : 애노테이션 기반의 컨트롤러인 @RequestMapping
1순위는 BeanNameUrlHandlerMapping : 스프링 빈의 이름으로 핸들러를 찾는다.

HandlerAdapter

0순위 = RequestMappingHandlerAdapter : 애노테이션 기반의 컨틀로러인 @RequestMapping
1순위 = HttpRequestHandlerAdapter : HttpRequestHandler 처리
2순위 = SimpleControllerHandlerAdapter : Controller 인터페이스(애노테이션X, 과거에 사용)

🎯 HandlerMapping을 순서대로 실행하여, 핸들러를 찾는다. 위에 예시에선 1순위인 BeanNameUrlHandlerMapping을 통해 @Component(/url)(빈이름)에 맞는 컨트롤러를 반환한다. 다음 HandlerAdapter의 supports()를 순서대로 호출해 2순위인 SimpleControllerHandlerAdapter Controller(예시에선 이 Controller 인터페이스를 구현하고 있다고 설명하지 않았다.)인터페이스를 지원하므로 대상이 된다. 핸들러 어탭터 실행 부분에선 디스패처 서블릿이 조회한 SimpleControllerHandlerAdapter를 실행하면서 핸들러 정보도 함께 넘겨주고, SimpleControllerHandlerAdapter는 핸들러인 OldController를 내부에서 실행하고, 그 결과를 반환한다.

보통은 제일 우선순위가 높은 @RequestMapping으로 찾는 게 일반적이다.

뷰 리졸버 - InternalResourceViewResolver

스프링 부트는 InternalResourceViewResolver라는 뷰 리졸버를 자동으로 등록하는데, 이때 application.properties에 spring.mvc.view.prifix, suffix 같은 설정을 등록 했다면 이런 설정 정보까지 사용해서 등록한다.

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

1 = BeanNameViewResolver : 빈 이름으로 뷰를 찾아서 반환한다.
2 = InternalResourceViewResolver : JSP를 처리할 수 있는 뷰를 반환

1.핸들러 어댑터 호출 -> 컨트롤러에서 return "form"이라면 form이라는 논리 뷰 이름을 획득하고
2.viewResolver호출 -> (1) form이라는 뷰 이름으로 viewResolver를 순서대로 호출한다.
(2) BeanNameViewResolver는 form이라는 이름의 스프링 빈으로 등록된 뷰를 찾아야 하는데 없다면
(3) InternalResourceViewResolver가 호출된다.
3.InternalResourceViewResolver -> 이 뷰 리졸버는 InternalResourceView를 반환한다.
4. 뷰 - InternalResourceView -> InternalResourceView는 Jsp처럼 포워드 forward()를 호출해서 처리할 수 있는 경우에 사용
5. view.render() -> view.render()가 호출 되고 InternalResourceView는 forward()를 사용해서 JSP실행..

@RequestMapping

@RequestMapping

  • RequestMappingHandlerMapping
  • RequestMappingHandlerAdapter

이 RequestMapping은 앞에 나온 RequestMappingHandlerMapping, RequestMappingHandlerAdapter의 앞글자를 따서 만들었다고 한다. 그리고 이제는 모두가 이걸 사용한다...

핸들러 매핑을 통한 핸들러 조회와 핸들러를 처리할 수 있는 핸들러어댑터를 찾아야하는 것들을 이 @RequestMapping이 한 방에 해결해준다...!!!!!

profile
No. Try not. Do or Do not. There is no try.

0개의 댓글