Spring/MVC

스프링 MVC 1편 - 4장. MVC 프레임워크 만들기 (김영한)

광터틀 2022. 8. 22. 15:00

스프링 MVC 1편 - 4장. 직접 MVC 프레임워크 만들기 스터디 (인프런 - 김영한 강사님)

 

이전까지 만든 MVC 패턴은 공통처리가 어렵다는 문제가 있다. 공통기능을 처리해줄 수문장 역할. 프론트 컨트롤러 패턴을 도입하자. 

<프론트 컨트롤러 도입 이전> <프론트 컨트롤러 도입 이후>

FrontController 장점 

1. 서블릿 하나로 클라이언트 요청을 받는다. 즉, 입구가 하나다. 

2. 프론트 컨트롤러가 요청에 맞는 컨트롤러를 찾아서 호출한다. 

3. 공통 처리가 가능하다. 

4. 프론트 컨트롤러를 제외한 나머지 컨트롤러는 서블릿을 사용하지 않아도 된다. 

 

스프링 웹 MVC의 DispatcherServlet이 FrontController 패턴으로 구현되어 있음. 

(DispathcerServlet에 관하여. https://mangkyu.tistory.com/18 )


V1. 프론트 컨트롤러 도입

 

FrontController 적용 이전과 이후 비교 - 내부 로직은 거의 안 바뀐다.

 

 

특징 :

1) 각 컨트롤러(MemberFormController, MemberListController, MemberSaveController) 는 ControllerV1을 상속받는다. 

2) 각 컨트롤러는 서블릿으로 작성하지 않는다. 

3) urlPatterns="/front-controller/v1/*" 이므로 /front-controller/v1 하위의 모든 항목에 대해 서블릿을 실행한다. 생성자를 통해 접속한 URI를 받고, Map에 데이터를 put한다. 

4) service 메소드를 통해 접속한 URI를 받고, ControllerV1 controller 변수에 알맞는 컨트롤러를 저장한 후, 컨트롤러의 process 실행한다. 

FrontControllerServletV1

FrontController를 만들었으나 각각의 컨트롤러에 뷰로 이동하는 부분이 중복되고 깔끔하지 않다. V2는 뷰를 별도로 만들어서 해결한다. 


V2. View 분리 

 

생성자로 viewPath를 받는다. 

컨트롤러마다 반복되던 부분을 render함수로 처리한다. 

MyView 클래스를 만듦으로서 각 컨트롤러는 다음과 같이 바뀐다. 

 

MyView를 분리하기 전(좌)과 분리한 후(우)

FrontControllerServletV2는 V1일 때와 다르지 않다. 

service 메소드에

view.render(request, response);

만 추가해주면 된다. 


 

V3. Model 추가

HttpServletRequest, HttpServletResponse를 없애보자. 

요청 파라미터 정보를 자바의 Map으로 대신 넘겨서 서블릿 종속을 제거하고 Model 객체를 별도로 만들자. 

 

이전엔 HttpServletRequest 를 통해 파라미터를 넘긴 대신, 프론트 컨트롤러가 paramMap에 담아서 호출해준다. 

응답결과로 뷰 이름과 뷰에 전달할 Model 데이터를 포함하는 ModelView 객체를 반환한다. 

 

MyView, ModelView

requestURI를 받아서 해당 URI에 알맞는 컨트롤러를 ControllerV3 controller에 저장한다. 

createParamMap 메소드를 통해 Map paramMap에 파라미터들을 저장한다.

ModelView mv에 controller.process의 실행결과인 ModelView 객체를 저장한다. 

mv에 저장된 viewName을 꺼내서 viewResolver 메소드를 통해 MyView를 생성하고, 

render()함수를 실행한다. 


 

V4. 단순하고 실용적인 컨트롤러

항상 ModelView 객체를 생성하고 반환하기보단 viewName만 반환하자. 

모델 객체를 FrontController에서 생성해서 넘겨준다. 


 

V5. 유연한 컨트롤러 

 

어떤 개발자는 ControllerV3방식으로 개발하고 싶고, 어떤 개발자는 ControllerV4방식으로 개발하고 싶다면? 어댑터 패턴을 이용해서 호환이 가능토록 하자. (유연하게 작동하도록 하자) 

 

● 핸들러 어댑터: 중간에 어댑터 역할을 하는 어댑터가 추가되었는데 이름이 핸들러 어댑터이다. 여기서 어댑터 역할을 해주는 덕분에 다양한 종류의 컨트롤러를 호출할 수 있다.

● 핸들러: 컨트롤러의 이름을 더 넓은 범위인 핸들러로 변경했다. 그 이유는 이제 어댑터가 있기 때문에 꼭 컨트롤러의 개념 뿐만 아니라 어떠한 것이든 해당하는 종류의 어댑터만 있으면 다 처리할 수 있기 때문이다. 

 

(컨트롤러를  포함하는 개념이 핸들러이다. 어노테이션이 나오면서 요즘은 안 쓴다)

 

ControllerV3HandlerAdapter, ControllerV4HandlerAdapter을 각각 만든다. 

(핸들러 어뎁터에서는 handlerinstanceofControllerV3, V5을 통해 파라마티로 받은 핸들러가 ControllerV3 혹은 V5인지 확인한다) 

어댑터를 만들어두면 여러 버전의 Controller의 호환이 가능하고, 새로운 Controller을 추가해도 기본 구조를 바꾸지 않아도 된다.