인프런 김영한 님의 스프링 강의이며, 섹션 3 - 서블릿, JSP, MVC 패턴을 정리한다.
이번 시간은 MVC 패턴에 대해 간단히 요약하며, 자세한 설명이 궁금하면 수강을 권장한다.
참고로 MVC 패턴은 스프링 MVC가 아니다!
MVC 패턴 - 개요
너무 많은 역할
이전 시간에 봤던 jsp를 보면 하나의 jsp 파일에 모든 비즈니스 로직과 html 태그들이 혼합된 형태로 시간이 갈수록 커져간다.
<%@ page import="hello.servlet.domain.member.MemberRepository" %>
<%@ page import="hello.servlet.domain.member.Member" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
MemberRepository memberRepository = MemberRepository.getInstance();
List<Member> members = memberRepository.findAll();
%>
<html>
<head>
<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>"
+ "<td>" + member.getId() + "</td>"
+ "<td>" + member.getUsername() + "</td>"
+ "<td>" + member.getAge() + "</td>"
+ "</tr>");
}
%>
</tbody>
</table>
</body>
</html>
변경의 라이프 사이클
비즈니스 로직과 UI는 서로 다른 역할인데, 이를 하나로 합쳐서 시간이 갈 수록 유지보수와 변화에 대응하기 힘들어진다.
기능 특화
뷰 템플릿은 렌더링에 최적화되어 있어 이 부분의 업무만 담당하는 게 효과적이다.
Model View Controller
MVC 패턴은 뷰와 컨트롤러의 영역으로 역할을 나눈 것이다. 웹 애플리케이션 보통 MVC 패턴을 사용한다.
MVC 용어
컨트롤러 : HTTP 요청을 받아 파라미터를 검증하고, 비즈니스 로직을 실행 후 뷰에 전달할 데이터를 모델에 담는다.
모델 : 뷰에서 출력할 필요한 데이터를 담는다.
뷰 : 모델의 데이터를 이용해서 화면(HTML)을 그린다.
MVC 이전
비즈니스와 뷰 로직이 하나로 합쳐진 형태
MVC 패턴1
비즈니스와 뷰 로직이 분리되고 모델을 이용해서 뷰에 필요한 데이터를 비즈니스 로직이 전달한다.
컨트롤러 안에는 비즈니스 로직과 데이터베이스 접근 등 다양한 역할이 모여있다.
MVC 패턴2
컨트롤러의 비즈니스 로직이 너무 많다 보니 역할에 맞게 분류된 형태다.
컨트롤러 안에 많던 역할이 비즈니스 로직, 데이터 접근으로 더 분리된다.
MVC 패턴 - 적용
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 dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response); // forword는 내부안에서 호출이 일어남.
}
}
/WEB-INF
이 경로 안에 JSP가 있으면 외부에서 직접 호출할 수가 없다. 컨트롤러를 통해서만 JSP를 호출할 수가 있다.
redirect vs forward
리다이렉트는 실제 클라이언트로 응답이 갔다가 클라이언트가 다시 리다이렉트로 요청을 보내서, 클라이언트가 인지가 가능하다.
하지만 포워드는 서버 내부에서 일어나기 때문에 클라이언트는 인지하지 못한다.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="save" method="post">
username: <input type="text" name="username" />
age: <input type="text" name="age" />
<button type="submit">전송</button>
</form>
</body>
</html>
form 태그의 action을 보면 save 뿐이다. / 를 생략하면 상대 경로로 시작한다.
현재 계층 경로는 /servlet-mvc/members 이니
action의 결과는 /servlet-mvc/members/save 가 된다.
저장 로직과 결과를 받아올 jsp 코드를 확인해보자.
@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);
// 데이터를 보관할 모델
request.setAttribute("member", member);
String viewPath = "/WEB-INF/views/save-result.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response); // forword는 내부안에서 호출이 일어남.
}
이전의 서블릿과 매우 흡사한 비즈니스 로직을 가진다.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</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>
뷰에서도 모델로 데이터를 출력하는 부분만 신경 쓰니 매우 간단해졌다.
목록 조회도 위와 비슷하니 생략한다.
MVC 패턴의 한계
이전에 비해서 많이 개선된 모습을 보여줬다. 하지만 컨트롤러에 매번 중복되거나 불필요한 코드들이 보인다.
MVC 컨트롤러의 단점
- 포워드 중복 : 뷰로 이동하는 코드가 항상 중복되고 있다.
- 뷰경로 중복 : 어떤 뷰를 보여줄 것인지 매번 경로가 중복되고 있다.
- 미사용 코드 발생 : HttpServletRequest, HttpServletRespons는 사용되지도 않는다.
공통 처리가 힘들다
중복을 공통 메서드로 분리한다 해도 매번 공통 메서드를 호출해주는 코드도 중복이다. 사람은 실수를 하는 법, 호출을 안 하면 에러가 발생한다.
'교육 및 인강 > 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술' 카테고리의 다른 글
MVC 프레임워크 만들기 - View 분리(v2), Model 추가(v3) (0) | 2021.07.05 |
---|---|
MVC 프레임워크 만들기 - 프론트 컨트롤러 패턴 소개, 도입 (0) | 2021.07.05 |
서블릿, JSP - 회원 관리 요구사항, 서블릿으로 만들기, JSP로 만들기 (0) | 2021.06.29 |
서블릿(Servlet) - HttpservletResponse 기본 사용법, HTTP 응답 데이터 단순 텍스트 & HTML & API JSON (0) | 2021.06.28 |
서블릿(Servlet) - API 메시지 바디 : 단순 텍스트, JSON (0) | 2021.06.28 |