오봉이와 함께하는 개발 블로그

스프링 MVC 1 - 프론트 컨트롤러 도입 v1 본문

BE/Servlet

스프링 MVC 1 - 프론트 컨트롤러 도입 v1

오봉봉이 2022. 8. 11. 19:26
728x90

프론트 컨트롤러 도입 - v1

구조

  1. 클라이언트가 요청
  2. 어떤 요청이든 FrontController가 요청을 받는다.
  3. HTTP URL 매핑 정보에서 컨트롤러를 조회한다.
  4. 조회한 컨트롤러를 호출한다.
  5. 컨트롤러에서 로직 수행 후 JSP로 forward
  6. JSP는 클라이언트에 응답한다.

FrontControllerServletV1 - 프론트 컨트롤러

// package hello.servlet.web.frontcontroller.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(); // 클라이언트 URL에서 controllerMap에 있는 URL중 하나를 찾아서 클래스를 생성해준다.

        ControllerV1 controller = controllerMap.get(requestURI);
        if(controller == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        controller.process(request, response);
    }
}
  • urlPatterns = "/front-controller/v1/*"
    • /front-controller/v1 를 포함한 하위 모든 요청은 이 서블릿에서 받아들인다.
  • controllerMap
    • key : 매핑 URL
    • value : 호출될 컨트롤러
  • service()
    • requestURI를 조회해서 실제 호출할 컨트롤러를 controllerMap에서 찾는다.
      • 없다면 404 상태코드를 반환
    • 컨트롤러를 찾고 controller.process(request, response)를 호출해서 해당 컨트롤러를 실행한다.

ControllerV1

// package hello.servlet.web.frontcontroller.v1;

public interface ControllerV1 {
    void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}

다형성을 위해 컨트롤러 인터페이스를 만든다.
각 컨트롤러들은 이 인터페이스를 구현하면 된다.
프론트 컨트롤러는 해당 인터페이스를 호출해서 구현과 관계없이 로직의 일관성을 가져갈 수 있다.

MemberFormControllerV1 - 회원 등록 폼 컨트롤러

// package hello.servlet.web.frontcontroller.v1.controller;

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

MemberSaveControllerV1 - 회원 저장 컨트롤러

public class MemberSaveControllerV1 implements ControllerV1 {

    private MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    public void process(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);

        request.setAttribute("member", member);

        String viewPath = "/WEB-INF/views/save-result.jsp";
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);
    }
}

MemberListControllerV1 - 회원 목록 컨트롤러

public class MemberListControllerV1 implements ControllerV1 {

    private MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    public void process(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);
    }
}

기존 코드의 구조를 바꿀 때는 구조를 바꾸는 것에만 집중하자.
구조를 바꾸면서 기존 코드에 문제점이 보여 코드도 같이 수정하게 된다면 복잡해서 뒤죽박죽 되돌릴 수 없는 결과가 나올 수 있다.

명심하고 명심하자.

출처 : 인프런 김영한 지식 공유자님 강의 - 스프링 MVC 1편 백엔드 웹 개발 핵심 기술
728x90
Comments