MVC 패턴

컴업·2021년 11월 11일
0

MVC 패턴 이전에는..

서블릿은 웹페이지를 동적으로 만드는 클래스입니다.

WAS가 HTTP 요청 메세지를 파싱해 Requeste, Response 객체를 만들어 서블릿에게 전달해주면, 서블릿은 이 두 객체를 이용해 동적으로 HTML 페이지를 만듭니다.

아래 코드는 서블릿이 동적으로 HTML 페이지를 생성하는 간단한 코드입니다.

@WebServlet(name = "tempServlet", urlPatterns = "/servlet/temp")
public class Temp extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        // 쿼리 파라미터 데이터 받아오기
        String userName = request.getParameter("username");

        // Html 페이지 만들기
        response.setContentType("text/html");
        response.setCharacterEncoding("utf-8");
        PrintWriter w = response.getWriter();
        
        w.write("<!DOCTYPE html>\n" +
                "<html>\n" +
                "<head>\n" +
                " <meta charset=\"UTF-8\">\n" +
                " <title>Title</title>\n" +
                "</head>\n" +
                "<body>\n" +
                "   <div>" +
                "       <span> 안녕하세요 " + userName + "님. </span>" +
                "   </div>" +
                "</body>\n" +
                "</html>\n");
    }
}

서블릿안에서 쿼리파라미터로 넘어온 회원 이름 정보를 Reqeust 객체 안에서 꺼내고 회원에게 인사하도록 동적으로 HTML 페이지를 만들었습니다.
이 서블릿의 service 메서드가 끝나면 WAS는 Response 객체에 담긴 정보를 바탕으로 HTTP 응답 메세지를 만들 것입니다.

그런데 보면 알겠지만 자바로 HTML 페이지를 만드는 일은 정말 지옥입니다.
컴파일 과정에서 에러로 걸리는 것도 아니라 오타가 나면 어디서 잘못됐는지 찾기도 어렵습니다.

또 지금은 코드가 단순해서 괜찮겠지만, 세션, DB, 페이지 구성 뭐시기 뭐시기... 처리해야할 로직이 점점 많아지면 이 서블릿 클래스의 길이는 수천 수만 줄이 될 것입니다.

이를 해결하기 위해 나온 것이 바로 MVC패턴입니다.




MVC 패턴

MVC 패턴은 비즈니스 로직과, 뷰 로직을 분리하고 그 사이 데이터 전달은 Model 객체를 통해 하는 패턴을 의미합니다.

뷰로직을 분리함으로서 우리는 자바로 HTML 페이지를 만드는 끔찍한 일을, JSP나 Thymleaf와 같은 HTML페이지를 만드는데 도가 튼 템플릿 엔진으로 간단하게 처리할 수 있게 되었습니다.

컨트롤러

@WebServlet(name = "tempServlet", urlPatterns = "/servlet/temp")
public class Temp extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 쿼리 파라미터 데이터 받아오기
        String userName = request.getParameter("username");

        // 모델에 데이터 담기
        request.setAttribute("username", userName);
        
        // 뷰 로직 호출
        String viewPath = "/WEB-INF/views/temp.jsp";
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);

    }
}

비즈니스 로직을 실행한 후 결과를 Request가 제공하는 Attribute 모델에 담았습니다. 이후 Dispatcher에 경로를 설정하고 forward로 뷰 로직을 호출했습니다.

참고

  • WEB-INF폴더에 담긴 파일은 브라우져 url창에 경로를 입력하는 방식으로는 접근 할 수 없다.
  • Forward: 서버 내부에서 다시 호출이 발생한다. 클라이언트에게 영향이 가지 않는다.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

  <div>
      <span> 안녕하세요 ${username}님. </span>
  </div>

</body>
</html>

JSP에서는 ${} 문법을 제공한다. 이를 통해 Request의 Attribute에 담긴 데이터를 간편하게 사용할 수 있습니다.


이렇게 우리는 컨트롤러(비즈니스로직), 모델(데이터), (HTML 페이지)로 역할을 나누어 좀 더 유지보수하기 수월한 서비스를 만들 수 있게되었습니다.

그럼에도 불구하고 서비스가 복잡해짐에 따라 여전히 컨트롤러가 담당하는 역할이 너무 많았습니다.

그래서 이제는 컨트롤러의 로직을 서비스(비즈니스 로직), 리포지토리(DB 접근)에게 분담하는 방식을 주로 사용합니다.





MVC 패턴의 한계

이러한 MVC 패턴에도 한계가있습니다.

먼저 view로 이동하기 위해서 아래와 같이 forward가 할상 호출되어야 하고,

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

때에 따라서 Response객체를 사용하지 않을 때 도 있지만, 항상 받아와야한다는 문제가 있습니다.

무엇보다 기능이 복잡해질수록 모든 컨트롤러에서 공통으로 처리해야할 로직이 증가할텐데 이를 공통처리하기 어렵다는 문제가 있습니다.

프론트 컨트롤러는 컨트롤러 호출 전에 먼저 공통기능을 처리하는 수문장 역할을 해
주는 녀석입니다.

스프링 MVC의 핵심도 바로 이 프론트 컨트롤러에 있습니다.

profile
좋은 사람, 좋은 개발자 (되는중.. :D)

0개의 댓글