JSP등장 이전
JSP의 등장 이전에는 클라이언트에게 동적인 코드를 제공하기위해서 Servlet내부에서 서비스 코드를 작성하여 HTML코드와 함께 응답을 해주었다. 클라이언트에게 동적인 화면을 제공해줄수는 있었지만, Servlet내부에서 비즈니스 로직과 HTML코드가 섞여있기 때문에 유지보수가 매우 어려웠고 HTML코드를 제공하는 것 또한 매우 어려웠다
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/simpleHtml")
public class SimpleHtmlServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 응답의 컨텐츠 타입을 HTML로 설정
response.setContentType("text/html;charset=UTF-8");
// HTML 코드를 작성하기 위해 PrintWriter 객체를 얻음
java.io.PrintWriter out = response.getWriter();
// HTML 코드 출력
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>간단한 HTML 페이지</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>안녕하세요! 서블릿에서 HTML을 출력했습니다.</h1>");
out.println("</body>");
out.println("</html>");
}
}
위와 같이 HTML코드를 작성하는데 어려움이 있으며, 이 HTML코드가 수천줄이 된다면 가독성이 매우 떨어질 것이다
JSP란
JSP는 Java Server Pages의 약자로 말 그대로 서버사이드 렌더링을 해주는 템플릿 엔진으로 내부적으로 서블릿을 사용하기 때문에 서블릿 기반의 기술들을 JSP내부에서 서블릿 컨테이너에 의해 처리되기 때문에 개발자 입장에서는 웹 페이지 개발을 보다 편리하게 할 수 있으며 비즈니스 로직과 HTML코드를 분리시켜 주어 비교적으로 유지보수에 용이하다는 장점을 줍니다
Servlet과 Java코드로 HTML을 보여줄 때는 Java코드안에 HTML이 있었지만 JSP는 HTML코드안에 동적인 자바 코드를 넣는다
아래는 JSP로 만든 간단한 회원등록 / 조회 코드이다
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="/save.jsp" method="post">
이름<input type="text" name="name"><br>
나이<input type="text" name="age"><br>
<button type="submit">전송</button>
</form>
</body>
</html>
form태그로 입력받은 데이터를 save.jsp 페이지로 넘기며 post메서드로 넘기기때문에 "name"과 "age" 키의 값은 쿼리파라미터 형식으로 URL이 아닌 HTTP message body에 담겨서 전송된다

아래 코드는 new-form.jsp의 form태그로부터 입력받은 데이터를 받아 저장소에 저장해준 뒤, 저장이 완료되었다는 것을 클라이언트에게 표시하기위해 Member객체에 입력된 결과를 동적인 HTML코드로 출력해준다
<%@ page import="hello.servlettest.member.MemberRepository" %>
<%@ page import="hello.servlettest.member.Member" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
MemberRepository memberRepository = MemberRepository.getInstance();
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
Member member = new Member(name, age);
memberRepository.save(member);
%>
<html>
<head>
<title>$Title$</title>
</head>
<body>
OK
<span>ID: <%=member.getId()%></span>
<span>NAME: <%=member.getName()%></span>
<span>AGE: <%=member.getAge()%></span>
<a href="/members.jsp">목록으로</a>
</body>
</html>
request 객체를 사용할 수 있는 이유는 JSP는 Servlet을 기반으로 동작하기 때문에 별도의 객체 생성 없이도 request,response와 같은 객체를 사용할 수 있다
<span>ID: <%=member.getId()%></span>
<span>NAME: <%=member.getName()%></span>
<span>AGE: <%=member.getAge()%></span>
위 코드가 바로 위에서 설명한 HTML코드안에 Java코드가 들어간다는 부분이며 이를 통해 클라이언트에게 저장되는 데이터의 정보를 동적으로 제공함을 의미한다

이제 2명의 회원을 등록한 뒤 회원 목록을 출력하는 코드를 살펴보겠다
<%@ page import="hello.servlettest.member.MemberRepository" %>
<%@ page import="hello.servlettest.member.Member" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
MemberRepository memberRepository = MemberRepository.getInstance();
List<Member> memberList = memberRepository.findAll();
%>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<table>
<thead>
<th>ID</th>
<th>Name</th>
<th>Age</th>
</thead>
<tbody>
<%
for(Member member : memberList){
out.write("<tr>");
out.write("<td>" + member.getId() + "</td>");
out.write("<td>" + member.getName() + "</td>");
out.write("<td>" + member.getAge() + "</td>");
out.write("</tr>");
}
%>
</tbody>
</table>
<a href="/new-form.jsp">등록하기</a>
</body>
</html>
아래와 같이 for문을 통해서 HTML코드를 표현할 수 있는데, 이 부분은 처음에 JSP없이 Servlet에서 HTML코드를 출력하는 부분과 매우 유사하며 동적인 HTML을 제공할 수는 있지만 결국 Java코드 안에 HTML코드가 들어가게되는 단점이 나타나게 된다.
<%
for(Member member : memberList){
out.write("<tr>");
out.write("<td>" + member.getId() + "</td>");
out.write("<td>" + member.getName() + "</td>");
out.write("<td>" + member.getAge() + "</td>");
out.write("</tr>");
}
%>
이를 보수하기 위해서 EL, JSTL을 사용하면 아래와 같이 Java코드와 HTML코드가 함께 사용되는 것을 막을 수 있다
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<table>
<c:forEach var="member" items="${memberList}">
<tr>
<td>${member.id}</td>
<td>${member.name}</td>
<td>${member.age}</td>
</tr>
</c:forEach>
</table>
위와 같이 이전보다는 훨씬 깔끔하게 HTML코드를 작성할 수 있지만 <c:forEach>와 같이 커스텀 태그를 직접 만들어서 사용하기 때문에 본래 HTML코드 자체는 망가지게 된다. 물론 각각의 템플릿 엔진은 유니크한 장점과 단점을 가지고 있겠지만 최근에는 템플릿 엔진으로 Thymeleaf가 주목받고 있으며 Thymeleaf는 Spring 프레임워크에서도 공식적으로 지원하는 템플릿 엔진이기 때문에 JSP가 사장되고 있는 추세라고 할 수 있다.
Thymeleaf는 JSP와 다르게 HTML코드를 변형시키지 않으며 HTML코드를 변형시키지 않는다.
Thymleaf의 관련한 글은 나중에 추가로 작성
MVC패턴 등장이유
지금까지는 Servlet -> JSP로 넘어오게 된 이유를 살펴보았으며 Servlet에서 JSP로 넘어올 때 Java코드와 HTML코드가 함께 사용된다는 단점을 보수하기 위해서 JSP를 사용한다고 했다.
JSP코드를 사용하니 Java코드와 HTML코드를 분리할 수는 있었지만 결과적으로 보면 하나의 파일에 Java코드와 HTML코드가 함께 사용되고 있음을 알 수 있었다. (<% %>의 자바영역과 <html></html>의 HTML영역)
이는 하나의 JSP파일 안에서 비즈니스 로직과 뷰 렌더링을 모두 수행한다는 것을 의미하고 객체지향원칙에서도 SRP(단일 책임원칙)을 강조했으며 이는 유지보수가 어려워진다는 결과를 낳는다.
실제로 실무에서는 UI를 변경하는 일과 비즈니스 로직을 변경하는 일이 각각 다르게 발생하는 상황이 번번하기 때문에 UI와 비즈니스로직 각각 다른 변경의 라이프 사이클을 하나의 파일로 관리하는 것은 유지보수 측면에서 매우 좋지 않다고 한다
이러한 단점 즉, JSP 하나의 파일 안에 함께 존재하는 UI코드와 비즈니스 로직코드 (HTML&JAVA)를 분리하기 위해서 MVC패턴을 사용한다
MVC패턴
MVC패턴은 Model, View, Controller의 약자를 의미한다.
View: View는 화면을 렌더링하는 역할을 하며 간단히 말해서 HTML코드를 브라우저(사용자에게)를 통해 보여주는 역할을 한다. 이 때 JSP에서 <% %>영역 안에 있는 Java코드를 통해 HTML코드 안에서 동적으로 표시될 데이터를 받았었는데 View에서 동적인 데이터를 사용하기 위해 Model에 담겨있는 데이터를 사용한다.
Model: View에 출력할 데이터를 담아두며 View에서 필요한 데이터를 모두 모델에 담아 전달해주므로 View는 비즈니스 로직이나 데이터 접근을 몰라도 되며 사용자(클라이언트)에게 화면을 렌더링하는 단일책임의 역할을 만족하게 된다.
Contoller: 클라이언트로부터 HTTP요청을 받아 데이터 처리하기도하며 이 데이터를 비즈니스 로직을 통해 데이터를 가공하여 Model에 담아 View로 전달한다.
사용자의 입력 데이터를 검증하기도 하며 위에 코드에서 본 등록된 회원 DB에 저장, DB에 있는 회원을 Model에 담는 것을 의미한다
이 때, 컨트롤러에서 비즈니스 로직까지 처리해버리면 컨트롤러가 너무 많은 역할을 담당하기 때문에 일반적으로는 서비스라는 계층에서 비즈니스 로직을 처리하게 된다.
따라서 컨트롤러는 비즈니스 로직을 호출하여 데이터를 처리하고 Model에 담아 View로 전달하는 역할을 일반적으로 수행한다
MVC패턴에 대한 글은 MVC패턴 위주로 따로 작성하겠다.
'CS > HTTP' 카테고리의 다른 글
서블릿 (Servlet) (0) | 2024.04.07 |
---|---|
웹 서버와 웹 애플리케이션 서버(WAS) (1) | 2024.04.07 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!