MVC 패턴

강한친구·2022년 4월 20일
0

Spring

목록 보기
9/27

하나의 서블릿이나 JSP만으로 비즈니스 로직, 뷰, 렌더링까지 전부 처리하게 되면 너무 많은 역할이 주어지게 되고, 유지보수가 어려워진다. 따라서 이를 해결하기위해 MVC패턴을 사용한다.

이미지 출처

Controller와 View의 분리

컨트롤러

HTTP 요청을 받아서 파라미터를 검증하고, 비즈니스 로직을 실행한다. 그리고 뷰에 전달할 결과 데이터를 조회해서 모델에 담는다.

모델

뷰에 출력할 데이터를 담는다. 뷰가 필요한 데이터를 모두 모델에 담아서 전달해준다. 이에 뷰는 비즈니스 로직이나 데이터 접근을 몰라도 되고, 화면을 렌더링 하는 일에만 신경쓰면 된다.

모델에 담겨있는 데이터를 사용해서 화면을 그리는 일에 집중한다. HTML생성 부분을 담당한다.

MVC로 회원가입

가입 화면 출력

@WebServlet(name = "mvcMemberFormServlet", urlPatterns = "/servlet-mvc/members/new-form")
public class MVCMemberFormServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String viewPath = "/WEB-INF/views/new-form.jsp";
        RequestDispatcher requestDispatcher = request.getRequestDispatcher(viewPath);
        requestDispatcher.forward(request, response); // 제어권 넘김
        // 서버안에서 내부적으로 호출하는것이지, 리다이렉트 하는게 아니다.
    }
}

redirect vs forward
리다이렉트는 실제 클라이언트(웹 브라우저)에 응답이 나갔다가, 클라이언트가 redirect 경로로 다시 요청한다. 따라서 클라이언트가 인지할 수 있고, URL 경로도 실제로 변경된다. 반면에 포워드는 서버내부에서 일어나는 호출이기 때문에 클라이언트가 전혀 인지하지 못한다.
경로 viewpath를 지정해주고 request가 오면 자동적으로 controller에서 view로 넘겨주는 역할은 한다.

가입 후 화면출력

@WebServlet(name = "mvcMemberSaveServlet", urlPatterns = "/servlet-mvc/members/save")
public class MvcMemberSaveServlet extends HttpServlet {

    private final MemberRepository memberRepository = MemberRepository.getInstance();
    @Override
    protected void service(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 requestDispatcher = request.getRequestDispatcher(viewPath);
        requestDispatcher.forward(request, response);

request에서 받는 param들을 각 변수에 세팅하고 이를 가지고 멤버를 만들어서 저장하고 이를 Attribute를 세팅한 후, 이 값을 view로 넘겨서 view 로직에 맞춰 출력해준다.

전체 조회

@WebServlet(name = "mvcMemberListServlet", urlPatterns = "/servlet-mvc/members")
public class MvcMemberListServlet extends HttpServlet {
    private final MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Member> members = memberRepository.findAll();
        request.setAttribute("member", members);

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

마찬가지로 전체 조회를 위해 List를 어트리뷰트로 세팅하고 view에서 출력한다.

하지만 이런 MVC 패턴들에는 한계가 있다.

MVC의 한계

  1. viewpath 중복
    만약 jsp가 아니라 thymeleaf 같은걸로 바꾸면 전부 바꿔줘야한다.

  2. 공통중복
    포워드, view 같은 부분들이 중복되고 이를 매번 호출해야한다.

공통처리가 어렵다.
따라서 컨트롤러 호출 전 공통기능을 처리해주는 Front Controller 패턴이 필요하다. 스프링 MVC도 이 Front Controller에 있다.

0개의 댓글