💻본 포스팅은 '스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 김영한'님의 강의를 듣고 작성되었습니다.
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의
웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -
www.inflearn.com
[서블릿]
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@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);
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>");
}
}
- 서블릿을 통해 자바코드에 HTML을 쓰는 예제 코드입니다.
- 이 경우 HTML 코드를 전부 작성하기 위해서 위와 같은 방식으로 진행해야 하는데 이 방식은 매우 불편하기 때문에 이를 해결하기 위해서 JSP라는 템플릿 엔진을 사용해 HTML 코드에 자바를 쓰는 형식을 진행해볼 것입니다.
[JSP]
<%@ page import="java.util.List" %>
<%@ page import="hello.servlet.domain.member.MemberRepository" %>
<%@ page import="hello.servlet.domain.member.Member" %>
<%@ 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>");
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>
- 이 경우는 저장된 회원 리스트를 조회하면 보여주는 형식으로 HTML 코드에 자바를 넣어 사용하는 방식인 JSP 문법을 사용해 작성한 코드입니다.
- <% ~ %>를 사용하면 자바 코드를 넣어 사용할 수 있습니다.(자바 코드 입력 가능)
- <%= %>를 사용하면 자바 코드를 출력할 때 사용할 수 있습니다.
[JSP의 한계]
- 그러나 JSP의 경우 view 부분과 서비스 로직 부분이 섞여 사용되기 때문에 유지보수가 곤란다하는 단점이 있습니다.
- view 부분(UI)이 변경될 경우 UI부분만 변경을 해야하는데 이 경우엔 이 일이 쉽지 않다. 반대로 서비스 로직의 변경에 UI 변경이 불가피할 때도 많다.
- 결과적으로 JSP에 서비스로직과 UI적 부분이 섞여 사용할 땐 유지 보수가 어려워 이를 권장하지 않고 이 때 MVC 패턴을 적용한 방안이 해결 방안으로 등장하게 된다.
[MVC 패턴]
package hello.servlet.web.servletmvc;
import javax.servlet.RequestDispatcher;
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;
@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);
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta charset="UTF-8">
<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>
- View와 Controller Service Model 등을 각각 기능에 맞게 나누어 사용한다.
- 이경우엔 서블릿을 Controller로 JSP를 view로 사용하고 있다. 이때 model은 HttpServletRequest 객체를 사용한다.
[MVC 패턴 이전]
- 비지니스 로직과 뷰 로직을 같이 사용해 호출하면 한 번에 나오게 했다.
- 대표적인 예시가 JSP(템플릿 엔진)과 자바 코드를 함께 사용하는 것
- 대표적인 예시2가 서브릿 안에(자바코드 안에) HTML 코드를 함께 섞어 쓰는 것
[MVC 패턴 적용]
- Controller - 서비스 호출을 담당(이때 컨트롤러가 비지니스 로직을 포함하고 있는 일은 바람직하지 않음.)
- Service / Repository - 비지니스 로직으로 데이터를 접근할 때 이를 사용한다. (서블릿이 사용되는 곳이기도 하다. HTTP 스펙을 다 처리해주고 우리는 필요한 비지니스 로직을 구현하면 된다.)
- Model - 데이터를 전달하고 데이터를 참조할 때 사용하며 servlet에 request는 내부 데이터 저장소를 가져 이를 사용하여 데이터 전달과 참조가 가능하다.
- request.setAttribute(), request.getAttribute()
- View - 화면을 그리는 역할을 한다. (UI라고 생각하면 된다.)
[참고]
절대경로 - 폼 전송시 save가 가야하는 경로라면 save가 호출되고
상대경로 - 폼 전송시 save가 가야하는 경로라면 현재 URL이 속한 계층 경로 + save가 호출된다.
[MVC의 한계]
그러나 MVC에도 한계가 있다.
- 사용하지 않는 코드
- HttpServletRequest request, HttpServletResponse response 의 코드를 사용할 때도 있고 사용하지 않을 때도 있다.
- 코드의 중복
- 이를 해결하기 위해 메서드로 공통화해도 되지만 이때도 메서드를 항상 호출해야 하기에 번거롭다.
- 공통 처리가 어렵다.
- 기능이 복잡해질 수록 컨트롤러에서 공통으로 처리해야 하는 부분이 점점 더 많이 증가할 것이다. 단순히 공통 기능을 메서드로 뽑으면 될 것 같지만, 결과적으로 해당 메서드를 항상 호출해야 하고, 실수로 호출하지 않으면 문제가 될 것이다. 그리고 호출하는 것 자체도 중복이다.
- 이를 해결하기 위해서는 수문장 역할을 하는 프론트 컨트롤러 패턴을 도입해야 해결할 수 있다. (입구를 하나로 만드는 작업을 말한다.)
- 스프링 MVC의 핵심은 바로 이 프론트 컨트롤러에 존재한다.
'Back-End > Spring' 카테고리의 다른 글
[Spring MVC][스프링MVC 기본 기능] - 로그 (0) | 2022.03.23 |
---|---|
[Spring MVC][스프링MVC 구조] - 스프링 MVC (0) | 2022.03.18 |
[Spring MVC][서블릿/Servlet] - 2. HttpServletResponse (0) | 2022.03.04 |
[Spring MVC][서블릿/Servlet] - 1. HttpServletRequest (0) | 2022.03.04 |
[Spring MVC][웹 애플리케이션 이해] - 4. HTML, HTTP API, CSR, SSR (0) | 2022.03.01 |