빙응의 공부 블로그
[Spring]스프링 MVC 1편 - 서블릿, JSP, MVC 패턴 본문
📝서블릿과 JSP
서블릿
@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>");
}
}
JSP
<%@ page import="hello.servlet.domain.member.MemberRepository" %>
<%@ page import="hello.servlet.domain.member.Member" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
// request, response 사용 가능
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>
위 두 코드의 불편한 점은?
위의 코드들은 회원 저장 코드이다.
- 서블릿의 한계점
- 서블릿으로 개발할 때는 뷰(View)화면을 위한 HTML을 만드는 작업을 해야하여 지저분하다.
- JSP의 한계점
- 위의 코드처럼 한 곳에 JAVA 코드, 데이터를 조회하는 리포지토리 등등 다양한 코드가 모두 JSP에 노출
- JSP가 너무 많은 역할을 하기 때문에 유지보수에 매우 힘들다.
- MVP 패턴의 등장
- 비즈니스 로직은 서블릿 처럼 다른곳에서 처리하고, JSP는 목적에 맞게 HTML로 화면을 그리는 일에 집중 하는 것은 어떨까? -> MVC 패턴의 등장 배경
📝MVC 패턴
MVC 패턴의 등장 배경은 많은 문제점에서 나왔다.
너무 많은 역할
하나의 서블릿이나 JSP만으로 비즈니스 로직과 뷰 랜더링을 모두 처리하여, 너무 많은 역할을 하게되고 유지보수가 어려워진다.
변경의 라이프 사이클
View와 데이터 사이의 변경 라이프 사이클이 다르다. 예를 들어 UI를 일부 수정하는 일과 비즈니스 로직을 수정하는 일은 각각 다르게 발생할 가능성이 매우 높다. 대부분 서로 영향을 주지 않기 때문에 변경 라이프 사이클에 따라 따로 나눠 관리하는게 좋다.
기능 특화
특히 JSP 같은 뷰 템플릿은 화면을 렌더링 하는데 최적화 되어 있기 때문에 이 부분의 업무만 담당하는 것이 좋다.
Model View Controller
MVC 패턴은 모델, 뷰, 컨트롤러로 나뉘어져 있으며, 웹 애플리케이션은 보통 이 MVC 패턴을 사용한다.
- 컨트롤러
- HTTP 요청을 받아서 파라미터를 검증하고, 비즈니스 로직을 실행한다.
- 뷰에 전달할 결과 데이터를 조회해서 모델에 담는다.
- 모델 : 뷰에 출력할 데이터를 담는 곳, 뷰가 필요한 데이터를 모두 모델에 담아서 전달해주는 덕분에 비즈니스 로직이나 데이터 접근을 몰라도 되며, 뷰는 화면을 렌더링 하는 일에 집중할 수 있다.
- 뷰 : 모델에 담겨있는 데이터를 사용해서 화면을 그리는 일에 집중한다.
@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);
//Model에 데이터를 보관한다.
request.setAttribute("member", member);
String viewPath = "/WEB-INF/views/save-result.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">
</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 패턴은 컨트롤러를 거쳐 데이터를 저장하고 jsp에서 뷰를 보여준다.
MVC 패턴의 한계
- MVC 패턴 덕분에 컨트롤러의 역할과 뷰를 렌더링 하는 역할을 명확하게 구분할 수 있었다.
- 그러나 컨트롤러에 중복이 너무많고, 필요하지 않은 코드들이 많이 보인다는 단점이 있다.
- 포워드 중복
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
- ViewPath 중복
String viewPath = "/WEB-INF/views/new-form.jsp"
- 사용하지 않는 코드 발생
HttpServletRequest request, HttpServletResponse response
- 공통 처리가 어렵다
- 기능이 복잡해질 수 록 컨트롤러에서 공통으로 처리해야 하는 부분이 점점 많아진다. 단순히 공통 기능을 메서드로 뽑으면 될 것 같지만, 결과적으로 해당 메서드를 항상 호출해야한다.
정리해보면
중복이 많고 공통 처리가 어렵다!
해결은 다음 포스팅부터!
'Spring > 인프런_개념' 카테고리의 다른 글
[Spring]스프링 MVC 1편 - 구조 이해 (0) | 2024.01.11 |
---|---|
[Spring]스프링 MVC 1편 - 프론트 컨트롤러 (0) | 2024.01.09 |
[Spring]스프링 MVC - 웹 애플리케이션의 이해 (1) | 2024.01.06 |
[Spring]스프링 핵심 원리 - 빈 스코프 (0) | 2023.12.29 |
[Spring]스프링 핵심 원리 - 빈 생명주기 콜백 (0) | 2023.12.29 |