๐Ÿ“‹ Spring MVC - 3. ์„œ๋ธ”๋ฆฟ, JSP, MVC ํŒจํ„ด


์„œ๋ธ”๋ฆฟ, JSP, MVC ํŒจํ„ด

์„œ๋ธ”๋ฆฟ์œผ๋กœ ๋งŒ๋“ค์–ด๋ณด๊ณ , JSP๋กœ ๋งŒ๋“ค์–ด๋ณด๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ MVC๋กœ ๋งŒ๋“ค์–ด ๋ณผ ๊ฒƒ์ด๋‹ค!

์„œ๋ธ”๋ฆฟ์œผ๋กœ ๋งŒ๋“ค์—ˆ์„ ๋•Œ ์ผ๋ถ€ ์˜ˆ์ œ

@WebServlet(name = "memberListServlet", urlPatterns = "/servlet/members")
public class MemberListServlet extends HttpServlet {
    private MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        List<Member> members = memberRepository.findAll();
        PrintWriter w = resp.getWriter();
        w.write("<html>");
        w.write("<head>");
        w.write("    <meta charset=\"UTF-8\">");
        w.write("    <title>Title</title>");
        w.write("</head>");
        w.write("<body>");
        w.write("<a href=\"/index.html\">๋ฉ”์ธ</a>");
        w.write("<table>");
        w.write("    <thead>");
        w.write("    <th>id</th>");
        w.write("    <th>username</th>");
        w.write("    <th>age</th>");
        w.write("    </thead>");
        w.write("    <tbody>");
        for (Member member : members) {
            w.write("    <tr>");
            w.write("<td>" + member.getId() + "</td>");
            w.write("<td>" + member.getUserName() + "</td>");
            w.write("<td>" + member.getAge() + "</td>");
            w.write("    </tr>");
        }
        w.write("    </tbody>");
        w.write("</table>");
        w.write("</body>");
        w.write("</html>");
    }
}
  • ๋ณต์žกํ•˜์ง€๋งŒโ€ฆ ๋™์ ์œผ๋กœ ์›ํ•˜๋Š” HTML์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
  • ๊ฐ ์š”์ฒญ๋งˆ๋‹ค Servlet์„ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.
  • ์‘๋‹ตํ•  HTML์„ ์ž๋ฐ” ์ฝ”๋“œ ๋‚ด์— ์ž‘์„ฑํ•ด์•ผํ•œ๋‹ค.

JSP

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
import๋ฌธ ์ž‘์„ฑ
<%@ 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);

%>

<% %> ์•ˆ์— ์ž๋ฐ”์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ๋ทฐ๊ฐ€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋‹ค.
  • ์š”๊ตฌ์‚ฌํ•ญ์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๋ทฐ๋ฅผ ์ˆ˜์ •ํ•˜๋‹ค๊ฐ€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๋„ ๊ฐ™์ด ์ˆ˜์ •๋  ์ˆ˜ ์žˆ๋‹ค.
  • ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋–จ์–ด์ง„๋‹ค.

MVC

Servlet, JSP์˜ ๋ฌธ์ œ์ 

๋„ˆ๋ฌด ๋งŽ์€ ์—ญํ• 

ํ•˜๋‚˜์˜ ์„œ๋ธ”๋ฆฟ์ด๋‚˜ JSP๋งŒ์œผ๋กœ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ๋ทฐ ๋ Œ๋”๋ง๊นŒ์ง€ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋˜๋ฉด, ๋„ˆ๋ฌด ๋งŽ์€ ์—ญํ• ์„ ํ•˜๊ณ , ๋˜ํ•œ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ค์›Œ์ง„๋‹ค.

๋ณ€๊ฒฝ์˜ ๋ผ์ดํ”„ ์‚ฌ์ดํด

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ๋ทฐ์˜ ๋ณ€๊ฒฝ์˜ ๋ผ์ดํ”„ ์‚ฌ์ดํด์ด ๋‹ค๋ฅด๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด์„œ UI ๋ฅผ ์ผ๋ถ€ ์ˆ˜์ •ํ•˜๋Š” ์ผ๊ณผ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜์ •ํ•˜๋Š” ์ผ์€ ๊ฐ๊ฐ ๋‹ค๋ฅด๊ฒŒ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋งค์šฐ ๋†’๊ณ  ๋Œ€๋ถ€๋ถ„ ์„œ๋กœ์—๊ฒŒ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค.
์ด๋ ‡๊ฒŒ ๋ณ€๊ฒฝ์˜ ๋ผ์ดํ”„ ์‚ฌ์ดํด์ด ๋‹ค๋ฅธ ๋ถ€๋ถ„์„ ํ•˜๋‚˜์˜ ์ฝ”๋“œ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์ข‹์ง€ ์•Š๋‹ค.
๋ ˆ์ด์–ด๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ๊ธฐ์ค€์€ ๋ณ€๊ฒฝ ์ฃผ๊ธฐ๊ฐ€ ๋‹ค๋ฅผ ๋•Œ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ํŽธํ•˜๋‹ค.

๊ธฐ๋Šฅ ํŠนํ™”

๋ทฐ ํ…œํ”Œ๋ฆฟ์€ ํ™”๋ฉด์„ ๋ Œ๋”๋ง ํ•˜๋Š”๋ฐ ์ตœ์ ํ™” ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ถ€๋ถ„์˜ ์—…๋ฌด๋งŒ ๋‹ด๋‹นํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ํšจ๊ณผ์ ์ด๋‹ค.

Model View Controller

MVC ํŒจํ„ด์€ ์„œ๋ธ”๋ฆฟ์ด๋‚˜, JSP๋กœ ์ฒ˜๋ฆฌํ•˜๋˜ ๊ฒƒ์„ ์ปจํŠธ๋กค๋Ÿฌ(Controller)์™€ ๋ทฐ(View)๋ผ๋Š” ์˜์—ญ์œผ๋กœ ์„œ๋กœ ์—ญํ• ์„ ๋‚˜๋ˆˆ ๊ฒƒ์„ ๋งํ•œ๋‹ค.
์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋ณดํ†ต ์ด MVC ํŒจํ„ด์„ ์‚ฌ์šฉํ•œ๋‹ค.

Controller

HTTP ์š”์ฒญ์„ ๋ฐ›์•„์„œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฒ€์ฆํ•˜๊ณ , ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์‹คํ–‰ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ทฐ์— ์ „๋‹ฌํ•  ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•ด์„œ ๋ชจ๋ธ์— ๋‹ด๋Š”๋‹ค.
์ค‘์•™์—์„œ ์กฐ์ข…ํ•˜๋Š” ์—ญํ• . (๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋‹ด์„ ์ˆ˜ ์žˆ์ง€๋งŒ, ์—ญํ• ์ด ๋„ˆ๋ฌด ๋งŽ์•„์ง€๊ธฐ ๋•Œ๋ฌธ์— ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ํ˜ธ์ถœํ•œ๋‹ค๊ณ  ํ•˜์ž.)

Model

๋ทฐ์— ์ถœ๋ ฅํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„๋‘”๋‹ค.
๋ทฐ๊ฐ€ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ๋ชจ๋ธ์— ๋‹ด์•„์„œ ์ „๋‹ฌํ•ด์ฃผ๋Š” ๋•๋ถ„์— ๋ทฐ๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด๋‚˜ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ์„ ๋ชฐ๋ผ๋„ ๋˜๊ณ , ํ™”๋ฉด์„ ๋ Œ๋”๋ง ํ•˜๋Š” ์ผ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

View

๋ชจ๋ธ์— ๋‹ด๊ฒจ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ™”๋ฉด์„ ๊ทธ๋ฆฌ๋Š” ์ผ์— ์ง‘์ค‘ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” HTML์„ ์ƒ์„ฑํ•˜๋Š” ๋ถ€๋ถ„์„ ๋งํ•œ๋‹ค.

MVC ์ ์šฉํ•˜๊ธฐ

  • ์„œ๋ธ”๋ฆฟ์„ ์ปจํŠธ๋กค๋Ÿฌ๋กœ ์‚ฌ์šฉ
  • JSP๋ฅผ ๋ทฐ๋กœ ์‚ฌ์šฉ
  • HttpServletRequest ๊ฐ์ฒด๋ฅผ ๋ชจ๋ธ๋กœ ์‚ฌ์šฉ (request.setAttribute() , request.getAttribute() ์‚ฌ์šฉ)

MvcMemberFormServlet

@WebServlet(name = "mvcMemberFormServlet", urlPatterns = "/servlet-mvc/members/new-form")
public class MvcMemberFormServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String viewPath = "/WEB-INF/views/new-form.jsp";
        RequestDispatcher requestDispatcher = req.getRequestDispatcher(viewPath); // ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ทฐ๋กœ ์ด๋™
        requestDispatcher.forward(req, resp); // ์„œ๋ธ”๋ฆฟ์—์„œ JSP๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
    }
}
  • dispatcher.forward() : ๋‹ค๋ฅธ ์„œ๋ธ”๋ฆฟ์ด๋‚˜ JSP๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค. ์„œ๋ฒ„ ๋‚ด๋ถ€์—์„œ ๋‹ค์‹œ ํ˜ธ์ถœ์ด ๋ฐœ์ƒํ•œ๋‹ค.
    ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๊ฐ”๋‹ค๊ฐ€ ์˜ค๋Š”๊ฒŒ ์•„๋‹Œ(๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๊ฐ€ ์•„๋‹Œ), ์„œ๋ฒ„ ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœํ•œ ๊ฒƒ์ด๋‹ค.
  • /WEB-INF : ์ด ๊ฒฝ๋กœ์•ˆ์— JSP๊ฐ€ ์žˆ์œผ๋ฉด ์™ธ๋ถ€์—์„œ ์ง์ ‘ JSP๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์–ด ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•œ๋‹ค.

redirect vs forward

  • redirect : ์‹ค์ œ ํด๋ผ์ด์–ธํŠธ(์›น ๋ธŒ๋ผ์šฐ์ €)์— ์‘๋‹ต์ด ๋‚˜๊ฐ”๋‹ค๊ฐ€, ํด๋ผ์ด์–ธํŠธ๊ฐ€ redirect ๊ฒฝ๋กœ๋กœ ๋‹ค์‹œ ์š”์ฒญํ•œ๋‹ค.
    ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ธ์ง€ํ•  ์ˆ˜ ์žˆ๊ณ , URL ๊ฒฝ๋กœ๋„ ์‹ค์ œ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค.
  • forward : ์„œ๋ฒ„ ๋‚ด๋ถ€์—์„œ ์ผ์–ด๋‚˜๋Š” ํ˜ธ์ถœ์ด๊ธฐ ๋•Œ๋ฌธ์— ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ธ์ง€ํ•˜์ง€ ๋ชปํ•œ๋‹ค.

MvcMemberSaveServlet

@WebServlet(name = "mvcMemberSaveServlet", urlPatterns = "/servlet-mvc/members/save")
public class MvcMemberSaveServlet extends HttpServlet {
    MemberRepository memberRepository = MemberRepository.getInstance();

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

        // ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง
        Member member = new Member(username, age);
        memberRepository.save(member);

        // Model์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๊ด€ํ•œ๋‹ค. - req ๊ฐ์ฒด์— Map์ด ์žˆ๋Š”๋ฐ ์—ฌ๊ธฐ์— ์ €์žฅํ•œ๋‹ค.
        req.setAttribute("member", member);

        String viewPath = "/WEB-INF/views/save-result.jsp";
        RequestDispatcher requestDispatcher = req.getRequestDispatcher(viewPath);
        requestDispatcher.forward(req, resp);
    }
}

save-result.jsp

<%@ 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>
  • ${} : jsp๊ฐ€ ์ œ๊ณตํ•˜๋Š” ํ”„๋กœํผํ‹ฐ ์ ‘๊ทผ๋ฒ•์œผ๋กœ, req์— ๋‹ด๊ฒจ์žˆ๋Š” attribute์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

MvcMemberListServlet

@WebServlet(name = "mvcMemberListServlet", urlPatterns = "/servlet-mvc/members")
public class MvcMemberListServlet extends HttpServlet {
    private MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        List<Member> members = memberRepository.findAll();

        req.setAttribute("members", members);

        String viewPath = "/WEB-INF/views/members.jsp";
        RequestDispatcher dispatcher = req.getRequestDispatcher(viewPath);
        dispatcher.forward(req, resp);
    }
}

members.jsp ์ผ๋ถ€

<c:forEach var="item" items="${members}">
    <tr>
        <td>${item.id}</td>
        <td>${item.username}</td>
        <td>${item.age}</td>
    </tr>
</c:forEach>
  • <c:forEach> : <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> ๋ฅผ ์„ ์–ธํ•ด์•ผํ•œ๋‹ค.

MVC ํŒจํ„ด์˜ ํ•œ๊ณ„

forward์˜ ์ค‘๋ณต

๋ฉ”์„œ๋“œ๋ฅผ ์ถ”์ถœํ•ด๋„ ๋˜์ง€๋งŒ, ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ๋งˆ์ € ์ค‘๋ณต์œผ๋กœ ์ผ์–ด๋‚œ๋‹ค.

ViewPath์— ์ค‘๋ณต

prefix์ธ /WEB-INF/views/ ์™€ suffix์ธ .jsp ๊ฐ€ ์ค‘๋ณต์œผ๋กœ ๋ฐœ์ƒํ•œ๋‹ค.
๋งŒ์•ฝ jsp๊ฐ€ ์•„๋‹Œ thymeleaf ๊ฐ™์€ ๋‹ค๋ฅธ ๋ทฐ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค๋ฉด ์ „์ฒด ์ฝ”๋“œ๋ฅผ ๋‹ค ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค.

์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ฝ”๋“œ

HttpServletRequest request, HttpServletResponse response

์œ„ ๊ฐ์ฒด๋Š” ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๊ณ , ์•ˆํ• ์ˆ˜๋„ ์žˆ๋‹ค.

๊ณตํ†ต ์ฒ˜๋ฆฌ๊ฐ€ ์–ด๋ ต๋‹ค.

์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๊ณตํ†ต์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„์ด ์ ์  ์ฆ๊ฐ€ํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์ƒ๊ฐํ•ด๋ณด์ž.
๋‹จ์ˆœํžˆ ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ๋ฉ”์„œ๋“œ๋กœ ๋ฝ‘์œผ๋ฉด ๋  ๊ฒƒ ๊ฐ™์ง€๋งŒ, ๊ฒฐ๊ณผ์ ์œผ๋กœ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ํ•ญ์ƒ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๊ณ , ์‹ค์ˆ˜๋กœ ํ˜ธ์ถœํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฌธ์ œ๊ฐ€ ๋œ๋‹ค.
๋˜ํ•œ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ ์ž์ฒด๋„ ์ค‘๋ณต์ด๋‹ค.

ํ”„๋ก ํŠธ ์ปจํŠธ๋กค๋Ÿฌ(Front Controller) ํŒจํ„ด์„ ๋„์ž…ํ•˜๋ฉด ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.


โœ๏ธ ๊น€์˜๋‹˜์˜ ์Šคํ”„๋ง MVC 1ํŽธ - ๋ฐฑ์—”๋“œ ์›น ๊ฐœ๋ฐœ ํ•ต์‹ฌ ๊ธฐ์ˆ  ๊ฐ•์˜ ๋…ธํŠธ โœ๏ธ