본문 바로가기

백앤드 개발/Java & Spring

[Spring boot] 서블릿, JSP을 활용한 MVC 패턴

*** 프론트 컨트롤러 패턴 ***
지금까진 서블릿을 컨트롤러로 하고 jsp 를 뷰로하는 mvc 패턴을 사용했다
이번 시간엔 프론트 컨트롤러 패턴을 도입해 다음 공통 기능을 처리한다.



FrontController 패턴 특징
프론트 컨트롤러 서블릿 하나로 클라이언트의 요청 받음
프론트 컨트롤러가 요청에 맞는 컨트롤러를 찾아 호출
httpservlet request 상속, 어노테이션 등 공통된 기능해 처리함
따라서 프론트 컨트롤러를 제외한 나머지는 서블릿을 사용할 필요가 없음
스프링 웹 MVC의 핵심도 바로 FrontController


*** v1 프론트 컨트롤러 도입 ***
목표: url 이 진입하고 요청 별로 맞는 컨트롤러를 호출하는 프론트 컨트롤러를 구현


개발순서:
1. interface ControllerV1: 서블릿과 비슷한 모양이 인터페이스 도입. 컨트롤러는 해당 인터페이스를 통해 로직의 일관성을 가져감
2-1 MemberFormControllerV1: 회원 등록 컨트롤러, new-form.jsp 호출

2-2. MemberSaveControllerV1: 회원 저장 컨트롤러, 인터페이스 구현
form 을 통해 전달된 username, age를 통해 member 객체 생성 > memberRepository에 저장 > 
request 에 member 객체 setting > save-result.jsp 호출 

2-3. MemberListControllerV1: 회원 목록 컨트롤러
findAll() 을 통해 멤버 리스트 받아오기 > request 에 member 리스트 setting > members.jsp 호출

3. FrontControllerServletV1: 프론트 컨트롤러
1) @WebServlet(urlPatterns = "/front-controller/v1/*": 하위의 모든 요청을 받아들임)
2) private Map<String, ControllerV1> controllerMap = new HashMap<>();
url 과 연결될 객체가 담길 HashMap 생성
3) FrontControllerServletV1() : 생성자를 통해 객체가 생성될 때 HashMap 에 사용할 주소값, 호출될 컨트롤러가 담김
4) ControllerV1 controller = controllerMap.get(requestURI); : request 로부터 url 을 꺼내와 controllerMap 에서 일치하는 컨트롤러를 찾음
5) 일치하는 controller 가 없다면 404 반환
6) 해당 컨트롤러 인스턴스 반환

실행순서:
1) 클라이언트에서 HTTP 요청
2) FrontControllerServletV1: url 매핑 후 해당하는 컨트롤러 호출
3) MemberSaveControllerV1 / MemberListControllerV1 / MemberFormControllerV1:  컨트롤러를 통해 jsp 포워딩
4) html 응답


*** v2 컨트롤러 별 공통로직 분리 *** 
목표: 모든 컨트롤러에서 중복되는 부분인 뷰로 이동하는 로직을 분리하는 객체를 생성

개발순서:
1. Myview: String path 변수 선언 및 생성자, dispatcher 를 통한 jsp 포워딩 구현, 컨트롤러마다 jsp 포워딩하는 부분을 구현하지 않아도 됨.
2. interface Controller2: Myview를 리턴하는 인터페이스 도입, 컨트롤러는 해당 인터페이스를 상속받아 Myview를 리턴
3-1. MemberFormControllerV2: 인터페이스 구현을 통해 회원등록폼 url 이 세팅된 Myview를 리턴하는 로직 구현.
3-2. MemberSaveControllerV2: 인터페이스 구현, form 을 통해 전달된 데이터 값을 memberRepository에 저장,
회원저장 url 이 세팅된 Myview를 리턴하는 로직 구현.
3-3. MemberListControllerV2: 인터페이스 구현,
memberRepository로부터 회원 목록을 불러와 request 에 setting 후
회원 목록 url 이 세팅된 Myview를 리턴하는 로직 구현.
4. FrontControllerServletV2: 
1) 생성자를 통해 호출가능한 url 목록 생성
2) sevice() 메서드 오버라이딩: 앞과 마찬가지로 request 로부터 url 을 꺼내와 controllerMap 에서 일치하는 컨트롤러를 찾고 일치하는 controller 가 없다면 404 반환
3) MyView 타입의 view 선언: controller.process() 는 MyView 를 리턴한다
4) view.render(request, response): 리턴받은 view로 랜더링함수를 통해 forward 호출 및 jsp 실행

실행순서: 
1) 클라이언트에서 HTTP 요청
2) FrontControllerServletV2: url 매핑 후 프론트 컨트롤러를 통해 해당하는 컨트롤러 호출
3) MemberSaveControllerV2 / MemberListControllerV1 / MemberFormControllerV1: 컨트롤러를 통해 viewpath 가 설정된 Myview 반환
4) FrontControllerServletV2: 반환된 Myview를 통해 render 함수 실행
5) Myview: jsp 포워딩
5) html 응답


*** v3 modelview 추가 ***
목표: 컨트롤러의 서블릿 종속성을 제거 (HttpServletRequest, HttpServletResponse) 하고 뷰이름의 중복을 제거하자 (/WEB-INF/views/new-form.jsp->new-form)

개발순서: 
1. ModelView: 뷰의 이름과 랜더링에 필요한 model 객체를 가진 modelView 개발, 컨트롤러에서 뷰에 필요한 데이터를 model 에 key,value 값으로 넣어줌
2. interface ControllerV3: modelview를 반환하는 인터페이스 생성
3. 지금부터 구현할 컨트롤러는 서블릿 기술을 전혀 사용하지않는다. 따라서 구현이 매우 단순하며 테스트도 쉽다.
3-1. MemberFormControllerV3: 인터페이스 기능 구현, url 전달 및 ModelView 리턴
3-2. MemberSaveControllerV3: 인터페이스 기능 구현,  , form 을 통해 전달된 데이터 값을 Member 객체에 담아 memberRepository에 저장, 
회원 생성 url 을 파라미터로 가지는 ModelView 생성, member객체를 ModelView 에 담아 ModelView 리턴
3-3. MemberListControllerV3: 인터페이스 기능 구현, memberRepository 회원 리스트를 조회한 값을 가지는 members 객체 선언 
회원 목록 url 을 파라미터로 가지는 ModelView 생성, members객체를 ModelView 에 담고 ModelView 리턴
4. Myview render() 개발, request/response, Map<String, Object> (전달될 파라미터 정보) 를 파라미터로 전달받아 jsp 를 포워딩하는 함수 구현
5. FrontControllerServletV3: 
1) createParamMap() 매서드 개발: HttpServletRequest에서 파라미터 정보를 꺼내서 Map으로 변환, 해당 Map( paramMap )을
컨트롤러에 전달하면서 호출
2) viewResolver 개발: viewName을 파라미터로 받아 물리적 경로 경로 리턴
3) 생성자를 통해 호출가능한 url 목록 생성
4) sevice() 메서드 오버라이딩: request 로부터 url 을 꺼내와 controllerMap 에서 일치하는 컨트롤러를 찾고 일치하는 controller 가 없다면 404 반환
5) Map 타입의 paramMap 선언 및 createParamMap 호출: 앞서 개발한 createParamMap을 통해 파라미터 정보를 리턴 받음.
6) MyView 타입의 view 선언: viewResolver 를 통해 완전한 경로를 리턴받음
7) view.render(): request 파라미터 정보 전달 및 jsp 포워딩


구현 순서
1) 클라이언트에서 HTTP 요청
2) FrontControllerServletV3: url 매핑 후 프론트 컨트롤러를 통해 해당하는 컨트롤러 호출
3) MemberSaveControllerV3 / MemberListControllerV1 / MemberFormControllerV1: ModelView 반환
4) FrontControllerServletV3: viewResolver 호출
5) viewResolver: Myview 반환
6) FrontControllerServletV1: model 호출
7) Myview: jsp 포워딩 및 html 응답



*** v4 ***
모델객체 파라미터화


*** v5 핸들러 어댑터 패턴 적용 ***
어댑터 패턴은 호환이 불가능한 컨트롤러들을 동시에 사용하고 싶을때 사용된다.
핸들러 어댑터 목록을 만들고 컨트롤러 호출시 핸들러를 호출해 알맞은 핸들러(컨트롤러) 를 적용한다