스프링

[ Spring ] 고대의 서블릿을 찾아서(2) - 서블릿을 넘어 템플릿 엔진으로

do_it_zero 2024. 10. 12. 11:36

고대의 서블릿을 찾아서(1)에서는 @WebServlet을 이용하여 클라이언트의 요청 URL을 받고 해당 URL HTTP 요청을 HttpServletRequest 객체를 이용하여 데이터를 파싱 후 HttpServletResponse 객체에 html 코드를 입력하여 응답 데이터를 브라우저에 보냈다.
이 과정은 가장 큰 문제점은 자바 코드로 html을 작성해야 한다는 것이였다. 이러한 문제를 해결하기 위해 템플릿 엔진이 등장하게 된다.

템플릿 엔진으로 생긴 변화-jsp

자,먼저 클라이언트 HTTP요청 서버의 서블릿은 어떻게 처리하고 HTTP 응답을 만들었는지 코드로 봐보자.

== 회원 가입 ==

@WebServlet(name = "memberFormServlet",urlPatterns = "/servlet/members/new-form")
public class MemberFormServlet extends HttpServlet {
    
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");

        PrintWriter w = resp.getWriter();
        w.write("<!DOCTYPE html>\n" +
                "<html>\n" +
                "<head>\n" +
                "   <meta charset=\"UTF-8\">\n" +
                "   <title>Title</title>\n" + 
                "</head>\n" + 
                "<body>\n" +
                "<form action=\"/servlet/members/save\" method=\"post\">\n" +
                "   username: <input type=\"text\" name=\"username\" />\n" + 
                "   age:      <input type=\"text\" name=\"age\" />\n" +
                "   <button type=\"submit\">전송</button>\n" +
                "</form>\n" +
                "</body>\n" +
                "</html>\n");
    }
}

클라이언트가 http://localhost:8080/servlet/members/new-form 로 요청을 보내면 HttpServletResponse 객체는 자바 코드로 html을 만든 후 브라우저에 응답값을 보냈다.

같은 결과가 나오도록 jsp 코드를 보면

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>

    <head>
        <title>Title</title>
    </head>

    <body>
        <form action="/jsp/members/save.jsp" method="post">
            username: <input type="text" name="username" />
            age: <input type="text" name="age" />
            <button type="submit">전송</button>
        </form>
    </body>

    </html>

클라이언트는 http://localhost:8080/jsp/members/new-form.jsp 로 요청을 보내면 브라우저는 응답 html 데이터를 받는다.

이번에는 회원 저장을 비교해보자

== 회원 저장 ==

- 고대의 서블릿 - 

@WebServlet(name = "memberSavaServlet",urlPatterns = "/servlet/members/save")
public class MemberSaveServlet extends HttpServlet {
    
    private MemberRepository memberRepsository = MemberRepository.getInstance();

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("MemberSaveServlet.service");
        String username = req.getParameter("username");
        int age = Integer.parseInt(req.getParameter("age"));

        Member member = new Member(username, age);
        System.out.println("member = " + member);
        memberRepsository.save(member);
        
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");

        PrintWriter w = resp.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="spring.web.domain.member.MemberRepository" %>
<%@ page import="spring.web.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>

가장 큰 차이점은 html 코드를 자바코드로 작성하지 않는다는 것이다. 또한 HTML문서에 동적으로 변경해야 부분만 자바 코드를 넣게 되어 더 편리하게 쓸 수 있게 되었다.

그렇다면 위의 작성된 jsp가 어떻게 HttpServletResponse 처럼 브라우저에게 응답값을 내려줄 수 있을까?

JSP와 서블릿

JSP는 JSP 컨테이너에 의해 Servlet으로 변환되고, Sevelt Container에서 초기화 되고 서블릿 객체가 되어 클라이언트의 요청을 처리한다. JSP에 작성된 일반 HTML 태그들은 Servlet의 service()메서드 안에서 out.write() 메서드로 변환된다. 따라서 JSP 파일을 보면 html 태그들만 모인 것 같지만 실상은 서버 내부에서 서블릿이 되어서 마치 고대의 서블릿(1)과 같은 형태를 띄게 되는 것이다.

서블과 JSP의 한계

서블릿으로 개발할 때는 뷰화면을 위한 HTML을 만드는 작업이 자바 코드에 섞여서 복잡했다. JSP를 사용한 덕분에 뷰를 생성하는 HTML 작업을 깔끔하게 가져가고, 중간중간 동적 변경이 필요한 부분에만 자바 코드를 적용했다. 그럼에도 몇 가지 아쉬운 점이 있다.

<%@ page import="spring.web.domain.member.MemberRepository" %>
<%@ page import="spring.web.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>

회원 저장 jsp 코드를 보면 상위 반은 회원 저장을 위한 비즈니스 로직이고, 나머지 하위 절반은 결과를 HTML로 보여주기 위한 뷰 영역이다.
또한 코드를 보면 JAVA 코드, 데이터를 조회하는 memberRepository 코드 등 모두 jsp에 노출되어 있다. 즉, JSP가 너~~무 많은 역할을 한다는 단점이 있다.

이러한 단점을 고려하여 비즈니스 로직은 서블릿 처럼 다른곳에서 처리하고,JSP는 목적에 맞게 HTML로 화면을 그리는 일에 집중하도록 하는 MVC 패턴이 등장하게 된다.

참고 자료
https://dololak.tistory.com/138
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/