기존 MVC패턴의 한계를 극복하기 위해서 프론트 컨트롤러를 직접 만들어서 도입해 보았다.
작동 원리
1. front controller에서 요청 url을 가져와서 비교한다.
public FrontControllerServletV1() {
controllerMap.put("/front-controller/v1/members/new-form", new
MemberFormControllerV1());
controllerMap.put("/front-controller/v1/members/save", new
MemberSaveControllerV1());
controllerMap.put("/front-controller/v1/members", new
MemberListControllerV1());
}
이렇게 map에 key,value를 설정해서 요청 url에 맞는 controller를 가져온 후 실행한다.
String viewPath = "/WEB-INF/views/save-result.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
v1에는 모든 컨트롤러에서 view로 이동하는 부분이 중복이 있는데, 이 부분을 따로 처리해주는 객체를 만들었다.
public void render(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
이렇게 viewPath만 string으로 받아서 처리해준다
Map<String, Object> model = new HashMap<>();
모델 객체를 프론트 컨트롤러에서 생성해서 넘겨준다. 컨트롤러에서 모델 객체에 값을 담으면 여기에 그대로 담겨있게 된다
String viewName = controller.process(paramMap, model);
MyView view = viewResolver(viewName);
v3와 달라진 점은 이 두가지이지만 개발자 입장에서는 굉장히 편리하게 코드를 작성할 수 있게 되었다.
프레임워크나 공통 기능이 수고로워야 사용하는 개발자가 편리해진다
지금까지 우리가 개발한 프론트 컨트롤러는 한가지 방식의 컨트롤러 인터페이스만 사용할 수 있었는데, 어댑터 객체를 설계하여 들어오는 요청에 따라 모든 버전의 컨트롤러를 사용할 수 있게 만들었다.
이렇게 어댑터 목록을 만들어서 들어오는 요청에 맞는 controller가 존재하는지, 호환되는지를 확인하고 그에 맞는 handler가 컨트롤러를 호출하고 view를 반환해준다.
스프링 MVC
여기서 더 발전시키면 좋겠지만, 스프링 MVC의 핵심 구조를 파악하는데 필요한 부분은 모두 만들어보았다.
사실은 여러분이 지금까지 작성한 코드는 스프링 MVC 프레임워크의 핵심 코드의 축약 버전이고, 구조도 거의 같다.
스프링 MVC에는 지금까지 우리가 학습한 내용과 거의 같은 구조를 가지고 있다.