- 코딩 공부/Spring

[스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술] 섹션2 서블릿, JSP, MVC

방개입니다 2022. 8. 4. 11:56

 

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard

 

  • 자바 코드로 HTML을 작성해야하는 어려움이 있어서 JSP등장 
  • HTML코드에 JAVA언어를 넣어 동적인 웹페이지 생성 
  • JAVA코드로 HTML을 비효율적으로 작성하는 SERVLET단전 개선 
  • PAGE IMPORT 
    • <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  • JAVA 코드 삽입 
    • <% ~~ %>
  • JAVA 코드 출력 
    • <%= ~~ %>
<%@ 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>
<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>

 

JSP의 한계점

  • 비즈니스 로직이 JSP에 노출 
  • JSP가 비즈니스 로직 + VIEW의 역할을 모두 함 -> 규모가 커질수록 관리하기 힘듬 
  • 비즈니스 로직과 뷰가 한 곳에 있음 
  • 이러한 jsp의 한계 때문에 Model View Controller로 역할을 분리한 mvc패턴이 등장

 

MVC패턴의 개요 

  • 하나의 서블릿이나  JSP 만으로 모두 처리하려면 너무 많은 역할이 주어짐 
  • 변경 라이프 사이클
    • UI를 수정하는 일과 비즈니스 로직을 수정하는 일은 각각 다르게 발생할 가능성이 높기에 같이 있으면 유지보수하기에 좋지않다. 
  • JSP는 화면을 렌더링하는데 최적화 

 

Model, View, Controller 

 

컨트롤러: http요청을 받아서 파라미터를 검증, 비즈니스 로직을 실핼한다. 그리고 뷰에 전달할 결과 데이터를 조회해서 모델에 담는다. 

 

모델: 뷰에 출력할 데이터를 담아둔다. 뷰가 필요한 데이터를 모두 모델에 담아서 전달해주는 덕분에 뷰는 비즈니스 로직이나 데이터 접근을 몰라도 되고, 하면은 렌더링 하는 일에 집중가능  

 

뷰: 모델에 담겨있는 데이터를 사용해서 화면을 그린느 일에 집중한다. 여기서는 html을 생성하는 부분을 말한다. 

 

- 컨트롤러에 비즈니스 로직을 둘 수도 있지만, 이렇게 되면 컨트롤러가 너무 많은 력할을 담당한다. 그래서 일반적으로 비즈니스 로직은 서비스라는 계층을 별도로 만들어서 처리한다. 컨트롤러는 비즈니스 로직이 담겨있는 서비스를 호출하는 역할을 담당. 

 

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);
}
}

위에는 회원등록 폼이며 dispathcer.forward(): 다른 서브릿이나 jsp로 이동할 수 있는 기능이다. 서버 내부에서 다시 호출이 발생한다. 

 

 

REDIRECT VS FORWARD 

리다이렉트는 실제 클리아언트에 응답이 나갔다가 클리언트가 REDIRECT결로로 다시 요청한다. 따라서 클라이언트가 인지할 수 있고, URL 경로도 실제로 변경된다. 반면에 포워드는 서버 내부에서 일어나는 호출이기 때문에 클라이언트가 인지하지 못한다. 

 

회원목록 컨트롤러 

 

@WebServlet(name = "mvcMemberListServlet", urlPatterns = "/servlet-mvc/
members")
public class MvcMemberListServlet extends HttpServlet {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
protected void service(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
System.out.println("MvcMemberListServlet.service");
List<Member> members = memberRepository.findAll();
request.setAttribute("members", members);
String viewPath = "/WEB-INF/views/members.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}

 

한계 

  • 포워드 중복: VIEW PATH를 지정하고 이동시키는 과정이 모든 SERVLET에 반복적으로 발생 
  • VIEWPATH의 중복: 모든 절대 경로를 입력해야 하기 때문에 VIEWPATH 입력시 중복 발생 
    • 사용하지 않는 코드: HttpServletRequest / HttpServletResponse 객체를 사용하지 않음에도 파라미터로 받는 경우가 존대 
  • 공통처리 어려움 
    • 공통으로 중복되는 부분을 하나로 처리하지 못해 전체적으로 중복이 많이 발생 

 


위의 점들 때문에 해결하기위한 FRONT CONTROLLER등장!