[MVC1] 4. MVC 프레임 워크 만들기

kiwonkim·2021년 7월 12일
0
post-thumbnail

이전 포스팅

MVC 패턴을 도입해 컨트롤러와 뷰의 기능을 분리했다.
컨트롤러는 비즈니스 로직(서비스, 리포지토리)를 호출하여 결과를 모델에 담아 뷰로 포워드한다.
뷰는 모델을 참조하여 동적 HTML을 만들어 클라이언트 브라우저에 출력한다.

그런데 MVC 패턴은 중복 코드가 많고 공통 처리가 어려운 문제가 있다. 이를 보완하여 프레임 워크를 만들어보자. 스프링도 이러한 고민으로 부터 시작된 프레임워크이다.



V1. 프론트 컨트롤러의 도입

기존 MVC 패턴은 url에 따라 각 매핑된 컨트롤러로 이동한다. 그래서 입구가 여러개라 공통처리가 어려웠던 것이다.
모든 컨트롤러 전에 수문장 역할의 컨트롤러를 놓으면 공통처리를 수행하기 수월할 것이다. 스프링의 핵심도 이 프론트 컨트롤러이다.

  • Form, Save, List 의 세 컨트롤러는 다형성으로 Controller 인터페이스를 구현한다.
  • 프론트 컨트롤러는 URI와 세 컨트롤러의 <String, Controller> 꼴의 Map을 갖고 있다.
  1. 클라이언트가 URI로 요청
  2. 프론트 컨트롤러가 Map 에서 해당하는 컨트롤러를 찾아 다형성으로 인터페이스의 메서드를 실행한다.
  3. 컨트롤러가 비즈니스 로직을 수행하고 View로 포워드 시킨다.
  4. View에서 JSP가 브라우저에 결과를 출력한다.

V2. View 분리

Form, Save, List의 세 컨트롤러에서 각 뷰로 이동하는 부분에 중복이 있었다.
(RequestDispatcher의 생성 및 forward)
컨트롤러가 View주소를 넘겨주면 해당 주소로 포워딩시켜주는 클래스를 따로 만들자.

  • MyView는 뷰 URI를 필드로 갖고. 해당 URI로 포워드 해주는 메서드 render()를 갖는다.
  1. 클라이언트가 URI로 요청
  2. 프론트 컨트롤러가 Map에서 해당하는 컨트롤러 찾아 다형성으로 인터페이스의 메서드 실행
  3. 컨트롤러는 수행 결과를 MyView 객체에 뷰 URI주소를 담아 반환
  4. 프론트 컨트롤러는 MyView.render() 를 호출해 해당 뷰로 포워드
  5. JSP로 이동되어 JSP가 브라우저에 결과를 출력


V3. 모델 도입 + 뷰 상대 경로

request에 setattribute로 수행결과를 저장하다보니 컨트롤러가 서블릿 종속적이다. 이를 해결하기 위해 컨트롤러의 비즈니스 로직 수행결과를 별도의 모델에 담아 뷰에게 전송하자.

뷰 URI주소가 /WEB-INF/views/new-form.jsp, /WEB-INF/views/save-result.jsp 와 같은 방식인데 접두사와 접미사가 중복된다. 컨트롤러가 상대경로인 new-form만 반환하면 절대경로로 변환해주는 뷰 리졸버를 도입하자.

  • 컨트롤러에서 request를 안쓰기로 했으므로. 프론트 컨트롤러는 request에 담긴 데이터를 getParameter로 꺼내 Map 에 담아 컨트롤러에게 넘겨준다.
  • 컨트롤러는 비즈니스 로직 수행결과 ModelView 객체를 생성해 반환한다. ModelView는 비즈니스 로직 수행 결과 변수를 담은 Map + 뷰 상대 경로를 담은 String 으로 구성된다.
  • viewResolver는 프론트 컨트롤러의 멤버 메서드
  1. 클라이언트가 URI로 요청
  2. 프론트컨트롤러가 요청의 모든 파라미터를 맵에 저장한 파라미터 맵 생성. 파라미터 맵을 인자로 넘겨주며 컨트롤러 인터페이스 메서드 호출
  3. 컨트롤러는 수행결과를 ModelView 객체에 담아 반환
  4. 프론트컨트롤러가 상대경로를 인자로 뷰 리졸버를 호출
  5. 뷰 리졸버는 절대 경로를 MyView 객체에 담아 반환
  6. MyView.render(model)로 model을 담아 JSP에게 포워드. JSP는 모델을 참고하여 브라우저에 출력.


V4. 모델을 프론트 컨트롤러가 관리

컨트롤러가 모델 + 상대경로인 ModelView 객체를 일일이 생성하여 반환하는게 번거롭다. 프론트 컨트롤러에서 Map으로 모델을 생성하여 컨트롤러 호출시 같이 넘겨주어 사용하자. 컨트롤러는 상대경로만 반환한다.

  • 프론트 컨트롤러에서 수행 결과 저장할 Map인 model 생성해 놓음.
  1. 프론트 컨트롤러에서 request 파라미터를 Map으로 변환한 paramMap과, 컨트롤러 수행결과를 저장할 Map인 Model을 매개변수로 전달하여 컨트롤러 실행.
  2. 컨트롤러는 매개변수 Model에 결과 변수를 저장하고 뷰 상대경로만 반환한다.


V5. 어댑터 패턴 적용

V3은 컨트롤러가 ModelView를 반환 V4는 프론트 컨트롤러가 Model을 매개변수를 넘겨주어 사용하며 컨트롤러는 View경로만 반환한다. V3와 V4 처리방식을 동시에 사용하기 위해 어댑터 패턴을 도입한다.

  • 핸들러 매핑에는 URL에 따른 컨트롤러 객체가 Map 으로 매핑됨.
  • 핸들러 어댑터에는 핸들러에 따른 처리 방식이 저장(V3, V4)
  1. 클라이언트가 URI로 요청
  2. 프론트 컨트롤러가 핸들러 매핑 정보에서 해당 URI와 매핑되는 핸들러(컨트롤러) 찾음.
  3. 프론트 컨트롤러가 어댑터 Map 을 순회하며 해당 컨트롤러를 처리할 수 있는 어댑터를 찾음. (InstanceOf를 통해 찾음)
  4. 프론트 컨트롤러가 어댑터의 handler 메서드 호출하면 어댑터는 핸들러를 호출하여 비즈니스 로직 수행. 결과를 ModelView에 담아 반환. (V4의 경우 어댑터가 View경로에 model을 추가해 프론트 컨트롤러에 반환한다)

나머진 V4와 동일



정리

V1: 프론트 컨트롤러의 도입으로 공통 처리 수행
V2: 뷰 포워드 부분 수행하는 MyView 객체 도입
V3: Model을 추가해 컨트롤러의 서블릿 의존성 제거. 뷰 리졸버 도입으로 뷰 이름 중복 부분 제거.
V4: 프론트 컨트롤러가 컨트롤러에 Model을 넘겨주는 방식으로 컨트롤러는 상대경로만 반환.
V5: 어댑터 도입으로 프레임워크를 유연하고 확장성 있게 설계 (다양한 처리 방법 추가 가능)

스프링 MVC는 위 프레임워크와 매우 유사한 구조를 갖는다.



본 글은 김영한님의 "스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술" 강의내용 및 이해한 내용을 정리한 것입니다.

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard

0개의 댓글

관련 채용 정보