MVC 프레임워크 1

Jan 17, 2023

4 mins read

1. 프론트 컨트롤러 패턴

  • 클라이언트의 요청을 받는 프론트컨트롤러를 하나 만들고 그 프론트컨트롤러가 요청에 맞는 컨트롤러를 찾아서 호출해준다.
  • 입구를 하나로 하여 공통로직을 수행한다.
  • 프론트컨트롤러를 제외한 나머지 컨트롤러들은 서블릿을 수행하지 않아도 된다.
  • 스프링MVC의 DispatcherServlet이 이 FrontController패턴으로 구현되어있다.
  • (인프런 수업 듣는중)

2. 프론트 컨트롤러 도입 - Version 1

  • 이름을 v1로 하여 이전에 MVC로 만든 회원관리 로직에 프론트 컨트롤러를 도입시켜 보자.
  • hello.servlet.web.frontcontroller.v1 패키지를 만들고 서블릿 컨트롤러 형태의 인터페이스 ControllerV1을 생성한다.
package hello.servlet.web.frontcontroller.v1;

import java.io.IOException;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public interface ControllerV1 {
	
	 void porcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
	 
}
  • hello.servlet.web.frontcontroller.v1.controller 패키지에 회원 등록 컨트롤러 MemberFormControllerV1를 생성한다.
package hello.servlet.web.frontcontroller.v1.controller;

import java.io.IOException;

import hello.servlet.web.frontcontroller.v1.ControllerV1;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class MemberFormControllerV1 implements ControllerV1 {

	@Override
	public void porcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String viewPath = "/WEB-INF/views/new-form.jsp";
		RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
		dispatcher.forward(request, response);
	}

}
  • hello.servlet.web.frontcontroller.v1.controller 패키지에 회원 저장 컨트롤러 MemberSaveControllerV1 생성한다.
package hello.servlet.web.frontcontroller.v1.controller;

import java.io.IOException;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import hello.servlet.web.frontcontroller.v1.ControllerV1;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class MemberSaveControllerV1 implements ControllerV1{
	
	private MemberRepository memberRepository = MemberRepository.getInstance();
	
	@Override
	public void porcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		String username = request.getParameter("username");
		int age = Integer.parseInt(request.getParameter("age"));
		
		Member member = new Member(username, age);
		memberRepository.save(member);
		
		//Model에 데이터 보관
		request.setAttribute("member", member);
		
		String viewPath = "/WEB-INF/views/save-result.jsp";
		RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
		dispatcher.forward(request, response);
		
	}

}
  • hello.servlet.web.frontcontroller.v1.controller 패키지에 회원 목록 컨트롤러 MemberListControllerV1 생성한다.
package hello.servlet.web.frontcontroller.v1.controller;

import java.io.IOException;
import java.util.List;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import hello.servlet.web.frontcontroller.v1.ControllerV1;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class MemberListControllerV1 implements ControllerV1{
	
	private MemberRepository memberRepository = MemberRepository.getInstance();
	
	@Override
	public void porcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		List<Member> members = memberRepository.findAll();
		
		request.setAttribute("members", members);
		
		String viewPath = "/WEB-INF/views/members.jsp";
		RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
		dispatcher.forward(request, response);
		
	}

}
  • 이제 프론트 컨트롤러를 hello.servlet.web.frontcontroller.v1 패키지에 FrontControllerServletV1으로 생성한다.
package hello.servlet.web.frontcontroller.v1;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import hello.servlet.web.frontcontroller.v1.controller.MemberFormControllerV1;
import hello.servlet.web.frontcontroller.v1.controller.MemberListControllerV1;
import hello.servlet.web.frontcontroller.v1.controller.MemberSaveControllerV1;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

//front-controller/v1/으로 들어오는 모든 요청을 컨트롤 한다.
@WebServlet(name = "frontControllerServletV1", urlPatterns = "/front-controller/v1/*")
public class FrontControllerServletV1 extends HttpServlet {
 
	private Map<String, ControllerV1> controllerMap = new HashMap<>();
	
	public FrontControllerServletV1(){
		controllerMap.put("/front-controller/v1/members/new-form", new MemberFormControllerV1());
		controllerMap.put("/front-controller/v1/members/save", new MemberSaveControllerV1());
		controllerMap.put("/front-controller/v1/members", new MemberListControllerV1());
	}
	
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("FrontControllerServletV1.service");
		
		String requestURI = request.getRequestURI();
		
		//다형성 사용 
		ControllerV1 controller = controllerMap.get(requestURI);
		
		if (controller == null) {
			response.setStatus(HttpServletResponse.SC_NOT_FOUND);
			return;
		}	
		
		controller.porcess(request, response);
	}
	
}
  • JSP는 이전에 만들어 두었던 것을 그대로 사용한다.
  • http://localhost:8080/front-controller/v1/members
    http://localhost:8080/front-controller/v1/members/new-form
    접속해보면 전에 MVC로 만든것과 같은 동작을 하는걸 확인할 수 있다.