본 프로젝트 자료는 김영한님의 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술을 참고 제작됐음을 알립니다.
모델(Model), 뷰(View), 컨트롤러(Controller)의 약자로 애플리케이션 구조를 구성하는 3가지 요소를 의미한다.
애플리케이션의 모든 데이터 정보를 가공해 보유하고 있는 컴포넌트다.
시각적인 UI를 의미
Model 과 View 를 제어하는 역할
이 3가지 요소는 각 컨셉에 맞게 세팅해줘야 진정한 의미가 생긴다.
과거에 설계한 프레임워크 -> 스프링 MVC 비교
스프링 MVC 의 프론트 컨트롤러를 담당한다고 보면 된다.
DispatcherServlet -> FrameworkServlet -> HttpServletBean -> HttpServlet
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
ModelAndView mv = null;
// 1. 핸들러 조회
// 핸들러 매핑을 통해 요청 URL에 매핑된 핸들러(컨트롤러)를 조회한다.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 2. 핸들러 어댑터 조회 - 핸들러를 처리할 수 있는 어댑터
// 핸들러를 실행할 수 있는 핸들러 어댑터를 조회한다.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 3. 핸들러 어댑터 실행 -> 4. 핸들러 어댑터를 통해 핸들러 실행 -> 5. ModelAndView 반환
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
private void processDispatchResult(HttpServletRequest request,
HttpServletResponse response,
HandlerExecutionChain mappedHandler,
ModelAndView mv, Exception exception) throws Exception {
// 뷰 렌더링 호출
render(mv, request, response);
}
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
View view;
String viewName = mv.getViewName();
// 6. 뷰 리졸버를 통해서 뷰 찾기,
// JSP의 경우: InternalResourceViewResolver 가 자동 등록되고, 사용된다.
// 7. View 반환
// 뷰 리졸버는 뷰의 논리 이름을 물리 이름으로 바꾸고, 렌더링 역할을 담당하는 뷰 객체를 반환한다.
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
// 8. 뷰 렌더링: 뷰를 통해 뷰를 렌더링 한다.
view.render(mv.getModelInternal(), request, response);
}
DispatcherServlet 으로 받은 요청을 Controller 로 보내지는데, 그런 요청이 어떤 룰로 컨트롤러에게 보내는지(매핑하는지), 그 방법을 정해주는 클래스가 바로 Handler 다.
HttpRequestHandler
서블릿과 가장 유사한 형태의 핸들러다.
public interface HttpRequestHandler {
void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
간단히 알아봤으니 구현볼려고 한다.
MyHttpRequestHandler
@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");
}
}
이대로 실행했을 때 빈 화면이 나오고 콘솔에 MyHttpRequestHandler.handleRequest 가 출력된다면 성공이다.
가장 우선순위가 높은 핸들러 매핑과 핸들러 어댑터는
1. RequestMappingHandlerMapping
2. RequestMappingHandlerAdapter
@RequestMapping 의 앞글자를 따서 만든 이름인데, 이것이 바로 지금 스프링에서 주로 사용하는 애노테이션 기반의 컨트롤러를 지원하는 매핑과 어댑터이다.
DispatcherServlet에게 뷰 정보를 전달하는 방법 중 하나인 뷰 리졸버가 있다.
String 타입의 뷰 이름을 줄 경우
이제 어느정도 뷰 리졸버를 알아봤으니 코드로 확인해보자.
@Component("/springmvc/old-controller")
public class OldControlller implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("OldControlller.handleRequest");
return new ModelAndView("new-form");
}
}
View를 사용할 수 있도록 return new ModelAndView("new-form"); 코드를 추가했다.
실행해서 웹 브라우저에 Whitelabel Error Page 가 나오고, 콘솔에 OldController.handleRequest 이 출력된다면 성공.
뷰 리졸버 - InternalResourceViewResolver
스프링 부트는 InternalResourceViewResolver 라는 뷰 리졸버를 자동으로 등록하는데, 이때 application.properties 에 등록한 spring.mvc.view.prefix, spring.mvc.view.suffix 설정 정보를 사용해서 등록한다.