- Spring MVC 는 Front Controller 패턴을 적용한 웹 애플리케이션 개발 프로젝트 이다.
Spring MVC의 구성 요소
DispatcherServlet
- Spring MVC는 스프링을 통해서 웹 MVC 애플리케이션을 개발하기 위한 아키텍처로 Front Controller 패턴을 사용한다.
- Front Controller 패턴
- 모든 클라이언트의 요청을 단일 진입점인 Front Controller가 처리하는 패턴
- 요청 처리 전 / 후 공통 모듈을 처리하기 용이
![](https://velog.velcdn.com/images/wnstj1128/post/4f831730-5553-4622-8ccf-4cf0f996d258/image.jpg)
- Spring MVC에서 Front Controller 역할을 담당하는 Servlet은 DispatcherServlet
- 이 Servlet은 Spring Web MVC에서 이미 잘 작성되어서 포함 되어 있기 때문에, 우리가 개발할 필요는 없다.
- DispatcherServlet은 클라이언트의 모든 요청을 접수하고 실제 동작은 하위 컨트롤러에게 위임해서 처리한다.
Infrastructure Components
- Infrastructure components는 Spring MVC에서 애플리케이션의 다양한 기능을 지원하고 요청 처리를 효율적으로 관리하기 위해 사용되는 객체들이다.
- DispatcherServlet이 요청을 처리하기 위해 사용하는 3가지
- HandlerMapping
- HandlerAdapter
- ViewResolver
- Handler ?
- 서브 컨트롤러들로 웹과 관련된 여러 업무를 실제 처리하는 것
- Controller라고도 불린다.
HandlerMapping
- 요청을 처리할 Handler가 누구인지를 DispatcherServlet에게 알려준다. HandlerMapping 덕분에 매핑 전략을 지원하는 유연한 URL 구성이 가능하다.
- RequestMappingHandlerMapping : @RequestMapping에 의해 빈 연결
- BeanNameUrlHandlerMapping : 빈의 이름에 있는 URL요청의 URL과 비교해서 빈 연결
HandlerAdapter
- 요청을 처리해줄 Handler를 연결하고 결과를 반환
- RequestMappingHandlerAdapter : @RequestMapping이 적용된 메서드를 호출해서 처리
- SimpleControllerHandlerAdapter : Controller 인터페이스를 구현한 컨트롤러를 이용해서 처리
HandlerMapping과 HandlerAdapter의 예시
@RequestMapping("/hello")
public String helloControllerMethod() {...}
@Bean(name = "/hello")
public Controller helloController() {
return new Controller() {
@Override
public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse res) {
return new ModelAndView("helloView");
}
}
}
ViewResolver
- 사용자의 요청에 적합한 View를 반환해서 결과를 보여줄 수 있게 한다.
- InternalResourceViewResolver : JSP와 같은 서버측 뷰 기술을 사용할 때 사용. prefix와 suffix로 파일 경로 지정
- BeanNameViewResolver : 빈 이름을 뷰의 이름으로 사용하여 직접 매핑
- ContentNegotiatingViewResolver : 다양한 컨텐트 타입(excel, pdf, text…)으로 데이터를 서비스 할 때
❗DispatcherServlet이 하위 컨트롤러를 호출하고 결과를 보여줄 때 직접 컨트롤러를 호출하지 않고 여러 컴포넌트를 끼워 넣는 이유 ?
- loose coupling 하게 관계를 유지하면서 다양한 형태의 호출을 지원하기 위해서
- 유연성과 나중에 추가될 수 있는 접근 방식에 대한 확장성을 유지
동작 방식
아래 그림에서 개발자는 노란색만 개발하면 된다. 즉, 나머지 부분들은 이미 스프링이 만들어 놓은 것이다.
![](https://velog.velcdn.com/images/wnstj1128/post/965677a9-7d18-441b-87f2-590e378d49a8/image.png)
- 브라우저에서 요청이 발생한다. 그 요청은 모두 DispatcherServlet이 받는다.
- DispatcherServlet은 HandlerMapping에게 요청을 처리할 Handler를 물어보고, HandlerMapping이 적절한 Handler를 알려준다.
- Handler마다 동작 방식이 다르므로 DispatcherServlet는 직접 Handler를 호출하지 않고, HandlerAdapter에게 요청을 전달한다.
- HandlerAdapter가 드디어 Handler를 호출하면서 request 처리를 요청하고, Handler는 요청을 분석 후 필요한 서비스(모델 영역)를 호출해서 비즈니스 로직을 처리한다.
- 서비스에서 반환된 데이터는 View에서 사용되는 경우가 많은데 View에서 쉽게 접근할 수 있도록 HttpServletRequest에 저장해 두는 것이 좋다. 이를 위해 스프링에서는 Model 타입의 객체를 사용한다.
- Servlet은 View의 이름을 return한다.
- DispatcherServlet이 ViewResolver을 호출하여 Controller가 리턴한 view name을 기반으로 적합한 View를 찾는다.
- DispatcherServlet이 View 객체에 처리 결과를 전달하여 보여준다.
- 실제 해당 View를 호출하면 템플릿 엔진이 동작해서 HTML을 구성한다.
- 이때 위에서 만든 Model의 데이터를 사용한다.
- View 객체는 해당하는 View를 호출한다. View는 Model 객체에 화면을 표시하는 데 필요한 객체를 가져와서 화면에 처리하고, Client에게 넘겨준다.
그림 출처
https://gtu-paper-solution.com/Paper-Solution/AdvancedJava-2160707/Winter-2018/4-c