Spring MVC에 대해 이해하기 쉽게 정리해보겠다.
그 전에 서블릿에 대한 개념만 잡고 들어가자.
서블릿 Servlet
- HTTP 요청 메시지를 파싱하고,, URL 확인하고 HTTP Method가 Get인지 Post인지 등을 확인하고 HTTP 응답 메시지 생성 등 되게 많은 작업들을 서블릿이 대신 수행해준다.
- 서블릿이 해주지 않았다면 개발자가 직접 다 해야하는 작업.
- urlPattern에 지정해둔 경로로 들어오면 해당 경로의 서블릿 로직(service())이 실행된다.
@WebServlet(name="helloServlet", urlPatterns="/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) {
// 애플리케이션 로직
}
}
- HttpServletRequest request가 HTTP 요청 메시지 파싱 정보를 가지고있어 개발자는 편하게 값을 꺼내서 사용하면된다.
- HttpServletResponse response를 사용해서 개발자는 편하게 HTTP 응답 메시지를 생성하면 된다.
[동작 과정]
- 사용자가 https://~~~/hello라는 경로로 들어옴.
- WAS는 들어온 HTTP 요청 메시지를 기반으로 request, response 객체를 생성함.
- 서블릿 컨테이너에 있는 helloServlet이 실행되는데 이때 2번 과정에서 생성한 request, response 객체를 파라미터로 넘겨준다.
- 서블릿을 지원하는 WAS에는 서블릿 컨테이너라는 것이 존재함.
- 서블릿 객체는 직접 생성한는게 아니다. 그냥 코드를 작성하면 서블릿 컨테이너가 알아서 생성, 호출, 종료를 해준다.
- helloServlet 실행이 끝나면 파라미터로 넘겨준 response를 기반으로 HTTP 응답 메시지 생성
- 응답 메시지 전달
MVC가 무엇일까?
Model, View, Controller다
- Model : View에 보낼 데이터를 담은 것
- View : Model에 담긴 데이터를 화면에 그려주는 것
- Controller : 요청 값 검증 및 비지니스 로직 호출하는 역할
스프링 웹 MVC 구조
스프링 웹 MVC의 DispatcherServlet
- 스프링 웹 MVC의 핵심이다.
- 컨틀롤러의 공통적으로 처리되는 로직 등을 처리하는 부분이라고 생각하면된다.
- HttpServlet을 상속받고있는 서블릿이다. (다이어그램 확인)
- DispatcherServlet을 서블릿으로 등록해야하는데 Spring boot같은 경우는 자동으로 서블릿을 등록하여 모든 경로(urlPattern="/")에 대해서 매핑한다.
- DispatcherServlet의 핵심 메서드는 doDispatch()이다.
- doDispatch()의 역할은 크게
- 핸들러(컨트롤러) 조회
- 핸들러(컨트롤러) 어댑터 조회 후 있으면 어댑터를 통해 핸들러(컨트롤러) 실행
- 핸들러(컨트롤러) 실행 결과 ModelAndView 반환
- ModelAndView에서 getViewName()을 통해 논리 ViewName을 뽑아낸 후 ViewResolver라는 인터페이스를 통해 실제 View를 찾음
- 찾은 View를 반환
- 최종적으로 뷰 렌더링
- 이러한 Spring MVC의 구조는 개발의 유연성을 확대할 수 있다.
- 만약 A개발자는 v1 컨트롤러로, B개발자는 v2 컨트롤러로 개발을 하고싶을 수 있는데 이때 핸들러 어댑터를 통해 실제 컨트롤러를 호출하기 때문에 어댑터가 맞춤 스펙으로 내부에서 처리해주기때문에 개발의 유연성이 확대된다고 볼 수 있다.
참고로 스프링은 이미 필요한 핸들러 매핑과 핸들러 어댑터를 대부분 구현해두었다.
핸들러 매핑과 핸들러 어댑터, 뷰 리졸버
스프링 부트가 자동 등록하는 핸들러 매핑과 핸들러 어댑터, 뷰 리졸버에서 중요한 것들만 가져왔다.
핸들러 매핑
- RequestMappingHandlerMapping
- 어노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
- BeanNameUrlHandlerMapping
- 우선순위대로 핸들러를 찾는다.
- 핸들러를 찾은 다음에 핸들러 어댑터를 찾는다.
핸들러 어댑터
- RequestMappingHandlerAdapter
- 어노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
- HttpRequestHandlerAdapter
- SimpleControllerHandlerAdapter
- 마찬가지로 우선순위로 핸들러 어댑터를 찾는다.
뷰 리졸버
뷰 리졸버를 통해서 논리 뷰를 실제 뷰 이름으로 반환해준다. (4번 과정)
1. BeanNameViewResolver
- 빈 이름으로 뷰를 찾아서 반환
2. InternalResourceViewResolver
- JSP를 처리할 수 있는 뷰를 반환
타임리프 같은 경우엔 타임리프 뷰 리졸버를 사용한다.
return "home";을 반환한다고 하면 타임리프 뷰 리졸버를 거쳐서
resources/templates/+"home"+.html가 반환되면서 렌더링 되는 것이다.
혹시 잘못알고있는 부분이 있다면 알려주시면 감사하겠습니다.
해당 포스팅은 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술의 내용을 공부하고 정리했습니다.