MVC 패턴은 왜 필요할까?

mark1106·2024년 4월 7일
0

스프링

목록 보기
5/5
post-thumbnail

MVC 패턴이란?

MVC는 Model, View, Controller의 약자로 하나의 하나의 애플리케이션, 프로젝트를 구성할 때 그 구성을 세 가지의 역할로 구분한 패턴이다.

❓왜 MVC 패턴을 사용해야 할까?
그 질문에 답하기 위해서 자바 웹 페이지가 어떻게 변화하였는지 알아볼 필요가 있다.


자바 웹 페이지의 변천사

1. 자바 + servlet으로 웹 페이지 만들기

자바 + servlet 코드 예시

@WebServlet(name = "memberSaveServlet", urlPatterns = "/servlet/members/save")
public class MemberSaveServlet extends HttpServlet {

    private MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("MemberSaveServlet.service");
        String username = request.getParameter("username");
        int age = Integer.parseInt(request.getParameter("age"));

        Member member = new Member(username, age);
        System.out.println("member = " + member);
        memberRepository.save(member);

        response.setContentType("text/html");
        response.setCharacterEncoding("utf-8");

        PrintWriter w = response.getWriter();
        w.write("<html>\n" +
                "<head>\n" +
                " <meta charset=\"UTF-8\">\n" +
                "</head>\n" +
                "<body>\n" +
                "성공\n" +
                "<ul>\n" +
                " <li>id="+member.getId()+"</li>\n" +
                " <li>username="+member.getUsername()+"</li>\n" +
                " <li>age="+member.getAge()+"</li>\n" +
                "</ul>\n" +
                "<a href=\"/index.html\">메인</a>\n" +
                "</body>\n" +
                "</html>");
    }
}

자바 코드와 servlet으로 HTML과 자바 data값을 조합하여 페이지를 만들 수 있다.


❌단점

자바 코드로 만든 HTML 문서가 비효율적이다.
자바 코드에 하나하나 하드 코딩하는 것이 상당히 번거롭다

❓ 자바 코드에 text로 html을 생성하기보단 기존 HTML에 동적으로 변하는 부분만 자바 코드를 넣을 수 없을까?


2. JSP(Java Server Pages)로 웹 페이지 만들기

jsp(java server pages)코드 예시

<%@ page import="mvc1practice1.mvc1practice1.domain.member.MemberRepository" %>
<%@ page import="mvc1practice1.mvc1practice1.domain.member.Member" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    MemberRepository memberRepository = MemberRepository.getInstance();
    System.out.println("save.jsp");
    String username = request.getParameter("username");
    int age = Integer.parseInt(request.getParameter("age"));
    Member member = new Member(username, age);
    System.out.println("member = " + member);
    memberRepository.save(member);
%>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
<ul>
    <li>id = <%=member.getId()%></li>
    <li>username=<%=member.getUsername()%></li>
    <li>age=<%=member.getAge()%></li>
</ul>
<a href="index.html">메인</a>
</body>
</html>

HTML 페이지에 <% ~ %>를 활용하여 자바 코드를 출력해 동적으로 페이지를 생성한다.

  • <% ~ %> : 자바 코드 입력
  • <%= ~ %> : 자바 코드 출력

💡JSP를 활용하여 View를 생성하는 HTML을 따로 분리할 수 있고 중간에 동적으로 변경이 필요한 부분만 자바 코드를 적용할 수 있다.

단점

HTML 페이지에 필요한 부분만 자바 코드를 넣어 자바 + servlet의 단점을 해결했지만 여전히 비즈니스 로직 + View가 함께 섞여있음

비즈니스 로직(자바 코드)은 서블릿에서, View(HTML 페이지)는 JSP에서 처리하여 비즈니스 로직과 View 역할을 분리할 순 없을까?


MVC 패턴

MVC 패턴의 등장 개요

  1. 위에서 말했듯이 비즈니스 로직과 View를 모두 담당해 많은 역할을 담당

  2. UI와 비즈니스 로직은 서로 종속적이지 않고 독립적이므로 변경의 라이프 사이클이 다른데 하나의 코드로 유지 보수하기 비효율적

💡 서블릿, JSP로 한번에 처리하던 것을 Controller, View로 분리하는 MVC 패턴 등장

MVC 패턴 구성

  1. Controller : HTTP 요청 받아 파라미터 검증, 비즈니스 로직 실행, View에 전달할 결과 데이터를 모델에 담음
    • service : Controller에서 비즈니스 로직을 처리하면 너무 많은 역할을 담당하므로 controller → service 호출하여 비즈니스 로직 처리
  2. Model : View에서 출력할 데이터 담음(View는 출력만 하는 역할로 비즈니스 로직 몰라도 됨)
  3. View : 모델에 담긴 데이터 출력.

MVC 패턴 예시

  1. 클라이언트가 Controller를 호출한다.
  2. Controller가 Service, Repository(Database)에 접근하여 필요한 데이터를 가져온다.
  3. 가져온 데이터를 Model에 저장한다.
  4. 필요한 데이터를 Model에 담았으면 View Model을 전달한다.
  5. View에서 필요한 데이터들을 Model에서 꺼내 사용한다.

서블릿(Controller) 와 JSP(View)를 사용한 MVC 코드

1. Controller(서블릿)

@WebServlet(name = "mvcMemberSaveServlet", urlPatterns = "/servlet-mvc/members/save")
public class MvcMemberSaveServlet extends HttpServlet {
    private 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);

        System.out.println("member = " + member);
        memberRepository.save(member);

        request.setAttribute("member", member);

        String viewPath = "/WEB-INF/views/save-result.jsp";
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);
    }
}
  • request.setAttribute()를 통해 request 객체(Model)에 필요한 데이터를 담는다.
  • dispathcer.forward() : request(Model)에 담은 data를 가지고 View로 이동한다.

2. View(JSP)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <meta charset="UTF-8">
</head>
<body>
성공
<ul>
  <li>id=${member.id}</li>
  <li>username=${member.username}</li>
  <li>age=${member.age}</li>
</ul>
<a href="/index.html">메인</a>
</body>
</html>
  • ${} : 해당 표현식은 request.getAttribute("data") 과 같은 뜻으로 request(model)에 담긴 데이터를 꺼내 사용한다.

💡MVC 패턴을 활용하여 자바 코드와 View를 분리하여 각자 역할을 분리하여 구현할 수 있다.

MVC 패턴의 한계

MVC 패턴을 활용하여 역할을 잘 분리하였지만 한계가 존재하는데 다음과 같다.

1. controller에서 코드 중복

//forward 중복
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);

//ViewPath 중복
String viewPath = "/WEB-INF/views/new-form.jsp";

2. 사용하지 않는 코드

HttpServletRequest request, HttpServletResponse response

response는 사용하지 않는 경우도 있지만 HttpServlet을 상속 받기 때문에 request, response를 항상 구현해야 한다.

3. 공통 처리 어려움

controller에 공통 기능이 많아질 경우 공통 메서드를 추출하면 될 것 같지만 HttpServlet을 상속 받고 service를 @Override 해서 사용하므로 메서드를 또 구현해야 함.

💡 컨트롤러 호출 전에 먼저 공통 기능을 처리하는 수문장 역할이 필요하다 -> 프론트 컨트롤러

📚참고

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard

profile
뒤돌아보면 남는 것은 사진, 그리고 기록 뿐

0개의 댓글