스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술을 공부하고 정리하는 포스트입니다.


MVC 프레임워크 만들기

개요

  • MVC 패턴에서 발생되는 많은 중복을 개선하기 위해 프론트 컨트롤러(Front Controller) 패턴 도입
  • 공통된 부분을 처리해주는 Front Controller로 중복을 줄일 수 있음
  • 점진적으로 개선
    • V1 : 프론트 컨트롤러(Front Controller) 패턴 도입
    • V2 : view render를 처리해주는 MyView 도입
    • V3 : 서블릿(Servlet) 종속성 제거 / View Resolver 도입으로 논리 뷰 이름 사용
    • V4 : V3 코드에서 반환타입을 논리 주소명으로 변경
    • V5 : 어댑터(Adapter) 패턴 도입으로 다양한 종류의 컨트롤러 처리
  • V5까지 점진적으로 개선시킨 구조는 실제 스프링 MVC의 핵심 구조와 동일

프론트 컨트롤러 도입 - V1

구조


코드

ControllerV1 - Interface


  • 다형성을 활용하기 위해 인터페이스 생성 : 여러 Controller가 비즈니스 로직을 수행하는 process 추상 메소드를 가진 인터페이스
    • 이 인터페이스를 호출하여 로직의 일관성을 가져감

MemberFormControllerV1


  • 회원가입 viewPath 생성 후, 해당 form으로 dispatch

MemberSaveControllerV1


  • HttpServletRequest 객체에 담긴 내용으로 member 생성 뒤 저장
  • viewPath 생성 후 dispatch

MemberListControllerV1


  • 모든 member를 조회한 뒤 Model 역할의 HttpServletRequest에 저장
  • viewPath 생성 후 dispatch

FrontControllerServletV1


  • urlPatterns = "/front-controller/v1/*" : /front-controller/v1으로 시작하는 모든 url path를 처리
  • Map<String, ControllerV1> controllerMap = new HashMap<>() : url path에 해당되는 컨트롤러를 매핑해주는 HashMap 생성
  • HttpServletResponse.SC_NOT_FOUND : 404 statusCode를 의미
  • 로직
    • url 파싱
    • 해당되는 controller 찾기 (없으면 종료)
    • 컨트롤러의 비즈니스 로직 수행

View 분리 - V2

구조


  • V1의 코드에서 화면 전환을 위한 dispatch과정을 MyView 객체로 처리해서 중복을 제거하는 모델

코드

MyView


  • HttpServletRequest / HttpServletResponse 객체를 받아서 dispatch 해주는 객체

ControllerV2


MemberFormControllerV2


MemberSaveControllerV2


MemberListControllerV2


FrontControllerServletV2



Model 추가 - V3

구조


  • 지금까지 컨트롤러에서 HttpServletRequest / HttpServletResponse를 사용하지 않아도 매개변수로 받음 : 필요한 것은 파라미터 정보
    • 불필요 & Servlet에 종속적
  • HttpServletRequest를 Model로 사용했음
    • Model을 별도로 생성해 Servlet의 종속성을 제거(추가로 View 이름을 받는 역할도 할 예정)

  • V3의 개선 사항
    • Servlet 종속성 제거 -> request Model 제거 : 컨트롤러가 서블릿 기술을 몰라도 동작. Model 객체 생성.
    • viewPath 중복 제거 -> View Resolver 추가

코드

ModelView


  • Servlet의 종속성을 제거하기 위해 별도로 추가한 Model
  • view에 가져가야 할 데이터가 담겨있는 model이라는 HashMap과 실제 물리 주소인 viewName을 가짐

ControllerV3


  • 모든 Controller는 ModelView를 반환해야 함

MemberFormControllerV3


MemberSaveControllerV3


  • 가야할 논리 주소를 매개변수로 ModelView 객체를 생성
  • ModelView 객체에 view에 넘길 데이터를 추가한 뒤 return!

MemberListControllerV3


FrontControllerServletV3


  • Map<String, String> paramMap : HttpServletRequest에 있는 데이터를 편하게 사용하기 위한 HashMap
  • createParamMap : HttpServletRequest에 있는 모든 데이터를 순회하면서 HashMap을 생성하는 메서드
  • viewResolver : viewName이라는 논리 주소를 받은 뒤 실제 주소가 있는 물리 주소를 가지는 MyView를 반환하는 메서드
    • 논리 뷰 이름 : members
    • 물리 뷰 경로 : /WEB-INF/views/member.jsp -> url path의 중복을 제거함 & 논리 주소만으로 소통 가능

MyView


  • model, HttpServletRequest, HttpServletResponse를 가지는 생성자 추가