개발일기

서블릿, JSP , MVC 패턴 회고 및 정리 본문

Spring/(김영한님)스프링 MVC 1편 - 백엔드 웹 개발 핵심기술

서블릿, JSP , MVC 패턴 회고 및 정리

한둥둥 2024. 3. 2. 12:08

웹사이트 View 무언가를 띄워서 보여줄 수 있도록 코드를 작성할 것이다. 

이 때, 회원이 등록하면 리스트로 보여질 수 있도록 코드를 작성하였는데.. 지금은 JSP도 안쓰는 시대이지만, 해보니 JSP가 선녀였다. 

 

 

form-servlet이다. 

package hello.servlet.web.servlet;

import hello.servlet.domain.member.MemberRepository;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;

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

        PrintWriter w = response.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");
    }
}

 

html 코드를 자바코드로 작성하여 보여주는 화면이며 굉장히 흠 별로다.  실수를 할 확률도 굉장히 높으며 라인이 너무 길어진다. 

 

 

해당 코드는 JSP의 코드이다. 자바코드 처럼 HTML 폼들을 일일히 작성하지 않아 실수할 확률이 줄어들긴하지만, JSP라는 파일 안에 자바 코드 + html코드가 한번에 들어가다 보니, 마찬가지로 라인이 굉장히 길어지며 추후에 복잡한 비즈니스로직이 있다면 천줄 , 2천줄이 되어버리면 유지보수를 하기 너무 힘들어지기 때문에 해당 방법도 좋지는 않다. 

<%@ page import="java.util.List" %>
<%@ page import="hello.servlet.domain.member.Member" %>
<%@ page import="hello.servlet.domain.member.MemberRepository" %>
<%@ 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>
</body>
</html>

 

위에 보면 <%  %>로 선언 한 부분에 자바코드를 작성할 수 있으며 이 때, 사용하는 객체들은 <%@ page import="" %> 를 사용하여 Import해주어야한다.

또한 html 코드 안에서 for문을 사용하여 반복문을 통하여 자바 코드를 사용해서 View를 그려줄 수 있다. 

 

 

이제부터는 완벽한 MVC패턴이라고 보기는 어렵고 미흡하지만 과거의 MVC? 패턴을 보자. 

 

MvcMemberFormServlet.java

@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); // 서버 내부에서 다시 호출 (클라이언트 왔다갔다 X 서버 안에서 내부적으로 호출이 일어남)
    }
}

해당 코드는  /servlet-mvc/members/new-form uri로 들어오는 것에대한 처리를 해주는 부분이며 Controller로 생각하면 될 것 같다. 

 

/views/new-form.jsp 라는 /WEB-INF 하위 디렉토리에 있는 new-form.jsp의 경로를 viewPath변수에 넣어주었다. 

WEB-INF는 Web Information의 약자로 web에 관련된 정보를 의미 

 

RequestDispatcher : RequestDispatcher는 클라이언트로부터 최초에 들어온 요청을 JSP/Servlet 내에서 원하는 자원으로 요청을 넘기는 역할을 수행하거나, 특정 자원에 처리를 요청하고 RequestDispatcher를 사용하여 b.jsp로 요청을 보낼 수 있다. 

 

또한 forward는 클라이언트에 다시 요청을 보내지 않고 내부적으로 해당 뷰로 이동시켜준다. 

하지만 redirect는 다시 Server에서 브라우저 클라이언트로 요청을 보내고 다시 클라이언트에서 이를 보내는 방식으로 이루어진다. 

 

package hello.servlet.web.servletmvc;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.List;

@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 {
        List<Member> members = memberRepository.findAll();

        request.setAttribute("members", members);
        String viewPaths = "/WEB-INF/views/members.jsp";
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPaths);
        dispatcher.forward(request,response);
    }
}

request.setAtrrubute를 통하여 데이터를 보내줄 수 있다. 

 

이때, 데이터는 기존처럼 사용할 수 있지만 

 

<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> Title 메인

 

해당 데이터는 JSTL 문법을 통하여 자바스크립트에서 쉽게 JAVA코드에 대한 위에서 setAttribute에 넣어준 변수 데이터를 손쉽게 view코드의 자바스크립트에서 사용할 수 있도록 만들어준다. 

 

여기까지 했지만, 아직도 중복되는 코드는 많으면 JAVA 코드를 보면 viewPath를 일일히 지정해주어야 넘겨줄 수 있으며 이를 frontController를 통해서 조금 더 쉽게 적은 양의 코드로 반복되는 부분을 지우도록 만들어 줄 것이다.

id username age
${item.id} ${item.username} ${item.age}
MVC 프레임워크 만들기 (V3, V4, V5)  (1) 2024.03.06
MVC 프레임워크 만들기 정리 및 회고 (V1, V2)  (0) 2024.03.06
Session2. 서블릿 정리및 회고 ( request, response)  (2) 2024.02.27
자바 백엔드 기술의 역사  (0) 2023.05.26
HTML, HTTP API, CSR, SSR  (0) 2023.05.23