FireDrago
[Servlet] MVC 패턴 업그레이드 하기 본문
이전 포스팅에서 MVC 패턴이 왜 출현하게 되었는지 살펴보았다.
이번 포스팅 에서는 MVC 패턴을 업그레이드 시키면서 MVC 패턴을 직접 만들어보고
Spring MVC의 기본원리까지 이해해보자
1. FrontController 도입
FrontController 는 각각의 Controller 에서 필요한 '공통작업'을 처리해준다.
만약 Spring MVC 프레임워크를 FrontController 라고 생각하고,
개발자가 작성하는 코드를 세부적인 Controller로 생각하면 이해가 더 쉬울 것이다.
먼저 FrontController를 작성하자

프론트 컨트롤러는 서블릿으로 등록된 컨트롤러고, 내부에 url 주소와 맵핑된 Controller 객체를 Map 으로 가진다.
클라이언트로부터 요청이 들어오면, url에 맵핑된 Controller 객체가 호출된다.
여러 컨트롤러 호출을 controller.process(request, response) 하나로 가능한 이유는 각각의 컨트롤러가
ControllerV1 인터페이스를 구현하고 있기 때문이다.


이 클래스가 개발자가 구현하는 클래스라고 볼 수 있다. 하지만 지금 위 클래스도 개선점이 있다.
1. FrontController 와 달리 서블릿이 아님에도 HttpServletRequest , HttpServletResponse 객체를 파라미터로 받고,
HttpServletRequest 객체를 모델로 사용하여 서블릿에 의존관계를 가진다.
2. 클래스마다 viewPath 의 경로를 모두 작성해야 한다. ( /WEB-INF/views/ .jsp 중복 코드 발생)
3. 클래스마다 RequestDispatcher 를 생성하고 forward 메서드를 호출해야한다. ( 중복코드)

위 그림에서 Controller 에 해당하는 ControllerV1 인터페이스가 있고, ControllerV1 인터페이스를
MemberSaveControllerV1 이 구현하고 있다.
2. 구조 개선
프론트 컨트롤러의 도입으로 개발자가 작성하는 컨트롤러 코드가 간결해졌다.
하지만 서블릿의존과 중복코드의 문제가 여전히 발생했다. 이번에는 이를 해결해보자

위 코드는 FrontController 의 service 메서드이다.
첫번째 코드의 단점을 해결하기 위해 더 많은 기능이 추가되었다.
1. HttpServletRequest 객체가 담고있는 요청 정보를 Map<String, String> paramMap 으로 옮겨 담고,
paramMap을 개별 컨트롤러에 파라미터로 전달한다. 개별 컨트롤러는 서블릿 의존성이 사라진다.
2. 개별 컨트롤러는 ModelView 객체를 결과로 반환한다. 리퀘스트를 대체한다.
3. viewResolver 메서드를 이용해 view 페이지 경로의 공통부분을 메서드에서 처리한다.
개별 컨트롤러는 자신이 담당하는 특정 논리경로만 ModelView에 담아서 전달하면 된다.
4. MyView 객체를 도입하여 forward를 개별 클래스에서 하지 않아도 된다. MyView 객체가 경로를 가지고
렌더링 까지 담당한다.

새로 도입된 MyView 클래스이다. MyView 클래스는 FrontController 에서 viewResolver 메서드를 통해 경로를 주입받는다.
그리고 주입받은 model 정보를 HttpServletRequest 객체에 담고 render 메서드를 통해 포워드를 실행한다.
이렇게 되면, 개별 클래스들은 더이상 직접 경로를 생성하고 포워드 할 필요가 없다.
그저 개별 클래스마다 다른 논리 경로를 ModelView에 담아서 반환만 하면 된다.


충분히 깔끔한 클래스가 되었지만 더 개선할 수 있는 점이 있다.
1. 매 클래스마다 ModelView 를 생성하고, view와 model 정보를 담아서 반환한다.
만약 FrontController 가 모델을 생성하여 주입한다면 매 클래스마다 ModelView를 생성할 필요가 없을 것이다.

3. Model 주입

프론트 컨트롤러에서 Map<String, Object> model 을 생성하여 컨트롤러를 실행할때 전달한다.
이렇게 되면 개별 컨트롤러는 ModelView를 매번 생성할 필요가 없다. view 정보를 반환하고,
model 에 담을 정보는 전달 받은 model에 담으면 되기 때문이다.
참고로 Map 의 제네릭이 Object 인 이유는 어떠한 객체도 담을 수 있어야 하기 때문에 가장 상위 객체인
Object를 사용하는 것이다.

이 코드의 형태는 Spring MVC 프레임워크를 사용할때 개발자가 작성하는 컨트롤러의 코드와 유사하다.
Spring MVC 프레임워크를 사용하면 개발자는 Model 객체를 주입받아 정보를 담고, 논리 경로를 문자열로 반환한다
최종적으로 FrontController가 Spring MVC와 유사한 역할을 하도록 MVC 패턴을 직접 만들었다고 볼 수 있다.

다음 포스팅에서는 Adapter 패턴을 활용하여, ModelView를 사용하는 컨트롤러와, 문자열을 반환하는 지금의 방식
둘 다 호환되도록 하는 Spring MVC 의 특징을 알아보자 실제로 Spring 은 ModelAndView를 반환하는 컨트롤러도
작동한다.
이 포스팅은 김영한님의 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술을 수강하고 작성되었습니다.
'프로그래밍 > Servlet' 카테고리의 다른 글
| [Servlet] MVC 패턴의 출현 (0) | 2024.01.24 |
|---|---|
| [Servlet] Servlet 사용법 (Request, Response) (0) | 2024.01.22 |
| [Servlet] 서블릿이란 (0) | 2024.01.19 |
| [Servlet] 세션(Session) (0) | 2023.07.07 |
| [Servlet] 포워드, 바인딩 (0) | 2023.07.04 |
