Web/MVC

EP4. MVC 패턴

MVC패턴이 등장하기 이전에는 하나의 서블릿이나 JSP에서 비즈니스 로직과 뷰 렌더링까지 모두 처리했다.

 

서블릿패턴에서 로직과 렌더링

package hello.servlet.web.servlet;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

@WebServlet(name = "memberListServlet", urlPatterns = "/servlet/members")
public class MemberListServlet extends HttpServlet {

    MemberRepository memberRepository = MemberRepository.getInstance();

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

        List<Member> members = memberRepository.findAll();

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

        PrintWriter w = response.getWriter();
        w.write("<html>");
        w.write("<head>");
        w.write("    <meta charset=\"UTF-8\">");
        w.write("    <title>Title</title>");
        w.write("</head>");
        w.write("<body>");
        w.write("<a href=\"/index.html\">메인</a>");
        w.write("<table>");
        w.write("    <thead>");
        w.write("    <th>id</th>");
        w.write("    <th>username</th>");
        w.write("    <th>age</th>");
        w.write("    </thead>");
        w.write("    <tbody>");
        for (Member member : members) {
            w.write("    <tr>");
            w.write("           <td>" + member.getId() + "</td>");
            w.write("           <td>" + member.getUsername() + "</td>");
            w.write("           <td>" + member.getAge() + "</td>");
            w.write("    </tr>");
        }
        w.write("    </tbody>");
        w.write("</table>");
        w.write("</body>");
        w.write("</html>");
    }
}

memberRepository에서 member를 find하는 비즈니스 로직과 서블릿 response에 view를 렌더링하는 코드가 한 곳에 모여있다.

 

 

 

view가 너무 기니까 차라리 HTML안에 자바코드를 넣으면 어떨까? -> JSP 등장

 

JSP

<%@ page import="hello.servlet.domain.member.Member" %>
<%@ page import="java.util.List" %>
<%@ page import="hello.servlet.domain.member.MemberRepository" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    MemberRepository memberRepository = MemberRepository.getInstance();
    List<Member> members = memberRepository.findAll();

%>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head><body>
<a href="/index.html">메인</a>
<table>
    <thead>
    <th>id</th>
    <th>username</th>
    <th>age</th>
    </thead>
    <tbody>
    <%
        for (Member member : members) {
            out.write(" <tr>");
            out.write("     <td>" + member.getId() + "</td>");
            out.write("     <td>" + member.getUsername() + "</td>");
            out.write("     <td>" + member.getAge() + "</td>");
            out.write(" </tr>");
        }
    %>
    </tbody>
</table>
</body>
</html>

 

보기에는 좋아졌지만 아직도 비즈니스 로직과 렌더링 코드가 같이 존재하는 모습이다.

 

서로 다른 역할을 하는 부분이 같이 존재한다면, 두 역할의 변경 사이클이 다르기 때문에 유지보수 하기가 어려워진다.

 

 

 

 

그래서 MVC 패턴이 등장한다.

 

 

M(model) V(view) C(controller)

 

컨트롤러 : HTTP 요청을 받아 파라미터를 검증하고, 비즈니스 로직을 수행하고 데이터를 "모델"에 담는다.

모델 : 뷰에 출력할 데이터를 모두 담아둔다.뷰 : 모델에서 데이터를 찾아 화면을 그린다 (HTML을 생성한다.)

 

 

 

redirect vs forward

리다이렉트 : 클라이언트가 서버로 호출하고 url이 실제로 변경되며 클라이언트가 바뀐 url로 서버에 다시 요청한다.

포워드 : 클라이언트가 서버를 호출하고 서버 내부에서 호출이 다시 일어난다. 그래서 클라이언트가 전혀 인지하지 못한다.