1. MVC패턴
1-1. 개요
- Servlet, JSP만으로 비즈니스 로직, 뷰랜더링까지 모두 처리하면 너무 많은 역할을 가지고있어 유지보수 어려움
- JSP 같은 뷰 템플릿은 화면을 렌더링 하는데 최적화 -> 화면 렌더링 역할만 맡기
- M: 뷰에 출력할 데이터를 담아두기
V: 델에 담겨있는 데이터를 사용해서 화면을 그림(HTML생성)
C: HTTP 요청을 받아서 파라미터를 검증하고, 비즈니스 로직을 실행 + 뷰에 전달
1-2. 한계
- 포워드 중복: view로 이동하는 코드가 항상 중복호출됨
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
- viewPath 중복: String viewPath = "/WEB-INF/views/new-form.jsp";
- 사용하지 않는 코드 존재: HttpServletRequest request, HttpServletResponse response
- 공통처리가 어려움
2. MVC 프레임워크 만들기
2-1. V1 프론트 컨트롤러 도입
- 각각의 Controller는 ControllerV1 가지고온다 (service는 컨트롤러 찾아주는 용도+process는 컨트롤러 실행)
- FrontController : /front-controller/v1/하위의모든url에 호출됨
=> controllerMap 으로 (매핑url, 호출된 컨트롤러)를 가지고오기
=> requestURI를 조회해서 실제 호출할 컨트롤러 찾음
=> controller.process를 호출해 해당 컨트롤러 실행
2-2. V2 View 분리
- 각각의 Controller에서 View 반환(MyView)
- FrontController : controller.process를 호출할 때 MyView를 반환함
=> view.render를 호출해 forward 로직을 수행해서 jsp로 넘어가서 화면보여줌
모든 컨트롤러마다 request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response); 가 있었는데,
=> 이를 컨트롤러마다 return new MyView("/WEB-INF/views/members.jsp");로 바꾸고
=> FrontController에서 MyView view = controller.process(request, response); view.render(request, response); 으로 넘겨줌
2-3. V3 Model 추가
[ 목적 ]
- 서블릿 종속성 제거 -> service의 HttpServletRequest, HttpServletResponse가 꼭 필요한가?
-> 요청파라미터 정보를 Map으로 넘기면 없어도 됨 => Model객체로 반환
- 뷰이름 중복 제거: /WEB-INF/views/new-form.jsp => new-form : 뷰의 논리 이름
=> 뷰의 물리이름은 프론트컨트롤러에서 처리
- FrontController : MemberFormControllerV3 호출 해야하는데 그 전에 createParamMap함수에서
HttpServletRequest에 있는 모든 parameter 가지고오기 => 각각 Controller에서 ModelView 객체반환 논리이름(new-form)을 가지고 옴 => makeView함수에서논리이름 -> 물리이름(전체주소)으로바꿔줌
(myView=전체주소반환, viewResolver는 물리이름으로 변환시켜주는 함수) => myView를가지고모델을같이넘기면서render진행
render할 때 ModelView의 객체도 같이 넘겨주기
2-4. V4 단순하고 실용적인 컨트롤러
-
Controller에서 ModelView가 아닌 ViewName만 반환(return "save-result")
V3: 모델안에 있는 값을 가지고와서 바꿔줬다면,
V4: String으로 가지고 옴
-
V3: String process(Map<String, String> paramMap);
V4: String process(Map<String, String> paramMap, Map<String, Object> model);
-
모델 객체 전달: Map<String, Object> model = new HashMap<>();
V3: 모델 객체를 각각 컨트롤러에서 생성
V4: 모델 객체를 프론트 컨트롤러에서 생성 (컨트롤러에서 모델 객체에 값을 담으면 여기에 담김)
2-5. V5 유연한 컨트롤러
[ 목적 ]
- 어떤사람은 V3, 어떤사람은 V4로 만들고싶어함
핸들러 어댑터: 다양한 종류의 컨트롤러 호출 가능
핸들러: 컨트롤러
-
ControllerV3HandlerAdapter, ControllerV4HandlerAdapter는 MyHandlerAdapter를 오버라이드함
supports는 V3, V4 넘어올 때 지원가능한지 여부 확인
handle에서는 V3, V4 각각 변경시켜주고 modelView반환시키기
-
FrontController: handlerMappingMap - 아무컨트롤러나다들어갈수있음(Object) -> V3의 물리적주소
handlerAdapters - 여러 adapter 중 하나 꺼내써야함
service - handler 조회(handlerMappingMap에서 requestURI가지고오기)
=> handlerAdapter조회 (MyHandlerAdapter) => handle호출해서 ModelView반환
=> 경로(/WEB-INF/views/members.jsp)찾기(viewResolver로 앞,뒤 주소붙이기)
=> view,render 호출
-
doDispatch가 handler, controller찾아주는 역할