๐Ÿƒ์„œ๋ธ”๋ฆฟ๊ณผ JSP

Spring MVC

7 minute read

์˜›๋‚ ์— ์‚ฌ์„œ ํ•œ๋ฒˆ๋„ ๋ณด์ง€ ์•Š์€ ์ฑ… ์ค‘์— JSP/์„œ๋ธ”๋ฆฟ์ด๋ผ๋Š” ์ฑ…์ด ์žˆ์—ˆ๋‹ค. ๋ง‰์—ฐํ•˜๊ฒŒ ์ž๋ฐ”๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ•˜๋Š” ์›น์ด๋ผ๋Š”๊ฒƒ ์ด์™ธ์—๋Š” JSP๊ฐ€ ๋ญ”์ง€ ์„œ๋ธ”๋ฆฟ์ด ๋ญ”์ง€ ์ „ํ˜€ ๊ฐ์ด ์—†์—ˆ๋‹ค. JSP๊ฐ€ ํ…œํ”Œ๋ฆฟ ์—”์ง„์ด๋ผ๋Š” ์‚ฌ์‹ค๋„ ์ด๋ฒˆ์—์„œ์•ผ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

์‹œ๋Œ€๋Š” ์ง€๋‚˜ ์Œฉ ์„œ๋ธ”๋ฆฟ, ๊ทธ๋ฆฌ๊ณ  JSP๋ฅผ ํ…œํ”Œ๋ฆฟ ์—”์ง„์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ผ์€ ๊ฑฐ์˜ ์—†๊ฒ ์ง€๋งŒ ์Šคํ”„๋ง์˜ ๊ทผ๊ฐ„์ด ๋˜๋ฏ€๋กœ ์กฐ๊ธˆ์€ ์ •๋ฆฌํ•ด๋ณด๋„๋ก ํ•˜์ž. ( ์•„๋ž˜ API๋ฅ˜๋Š” ์ข€ ์ƒ๋žตํ•ด๋„ ๋ ๊ฑฐ๊ฐ™๋‹ค.)

์Šคํ”„๋ง๋ถ€ํŠธ๋Š” ์„œ๋ธ”๋ฆฟ์„ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ(wrappingํ•˜์˜€์œผ๋‹ˆ ๋‹น์—ฐํ•˜๊ฒŒ๋„), ์˜ˆ์ œ ์ฝ”๋“œ๋Š” ๋ชจ๋‘ ์Šคํ”„๋ง ๋‚ด์—์„œ ์ž‘์„ฑํ•œ ๋ฒ„์ „์œผ๋กœ ํ•œ๋‹ค.

@ServletComponentScan // ์„œ๋ธ”๋ฆฟ ์ž๋™ ๋“ฑ๋ก  
@SpringBootApplication  
public class ServletApplication {  
  public static void main(String[] args) {  
    SpringApplication.run(ServletApplication.class, args);  
  }  
}  

์œ„์™€ ๊ฐ™์€ ์• ๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ์„œ๋ธ”๋ฆฟ์„ ์ž๋™๋“ฑ๋กํ•˜๋„๋ก ํ•œ ๋’ค, ์ฒซ ์„œ๋ธ”๋ฆฟ์„ ์ƒ์„ฑํ•˜์—ฌ ๋“ฑ๋กํ•˜๋„๋ก ํ•˜์ž.

@WebServlet(name = "helloServlet", urlPatterns = "/hello")  
public class HelloServlet extends HttpServlet {  
  @Override  
  protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
    System.out.println("HelloServlet.service");  
    System.out.println("request = " + request);  
    System.out.println("response = " + response);  
  
//http://localhost:8080/request-param?username=hello&age=20  
    String username = request.getParameter("username");  // ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฉ”ํ„ฐ  
    System.out.println("username = " + username);  
    response.setContentType("text/plain");  
    response.setCharacterEncoding("utf-8");  
    response.getWriter().write("hello " + username)  
  }  
}  

๋‹ค์งœ๊ณ ์งœ ์ฝ”๋“œ๋ถ€ํ„ฐ ์‚ดํŽด๋ณด์•˜๋Š”๋ฐ ๊ฐ„๋‹จํžˆ ์‚ดํŽด๋ณด๋ฉด ์•„์ง ์„ค๋ช…ํ•˜์ง€ ์•Š์€ ์„œ๋ธ”๋ฆฟ์ด ๋ฌด์—‡์ธ์ง€๋ฅผ ์•Œ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค๋ช…ํ•˜์ž๋ฉด ์›น ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ž๋ฐ” ํด๋ž˜์Šค์ธ ๊ฒƒ์ด๋‹ค.

@WebServlet ์„œ๋ธ”๋ฆฟ ์• ๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ์„œ๋ธ”๋ฆฟ ํด๋ž˜์Šค๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, name ๋ฐ urlPatterns์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์œ„ ์˜ˆ์ œ์˜ ์„œ๋ธ”๋ฆฟ์€ http://localhost:8080/hello์— ๋Œ€ํ•œ ์›น ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

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

protected void service(HttpServletRequest request, HttpServletResponse response)  

ํ˜„์žฌ์˜ ์Šคํ”„๋ง๋ถ€ํŠธ๋‚˜ ๋‹ค๋ฅธ ์›น ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ƒ๊ฐํ•ด๋ณด๋ฉด ์•„์‰ฌ์šธ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์ด๋ฏธ ์„œ๋ธ”๋ฆฟ๋งŒ์œผ๋กœ๋„ http request์— ๋Œ€ํ•œ ์ถ”์ƒํ™”๊ฐ€ ๋งŽ์ด ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค. HttpServletRequest๋ผ๋Š” ํด๋ž˜์Šค๊ฐ€ ์ด๋ฏธ request๋ฅผ ์ถ”์ƒํ™”ํ–ˆ๋‹ค๋Š” ์˜๋ฏธ๊ฐ€ ๋˜์ง€ ์•Š๊ฒ ๋Š”๊ฐ€? ๊ฐ„๋‹จํžˆ ์˜ˆ๋ฅผ ๋“ค๋ฉด Http request header์˜ Content-Length๋งŒ ํ•ด๋„ ๊ณ„์‚ฐ์—†์ด ์ž๋™์œผ๋กœ ์„œ๋ธ”๋ฆฟ์— ์ œ๊ณต์ด ๋œ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์„œ๋ธ”๋ฆฟ๋“ค์ด ์ €์žฅ๋˜๋Š” ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ๋Š” ์–ด๋””์— ์žˆ๋Š”๊ฑธ๊นŒ? ์ •๋‹ต์€ ํ†ฐ์ผ“(Tomcat) ์„œ๋ฒ„์ด๋‹ค. ์Šคํ”„๋ง๋ถ€ํŠธ๋ฅผ ํ†ตํ•ด ์„œ๋ธ”๋ฆฟ์„ ์ž‘์„ฑํ•˜๋ฉด ๋‚ด์žฅ๋œ ํ†ฐ์ผ“ ์„œ๋ฒ„๋ฅผ ํ†ตํ•ด ์„œ๋ธ”๋ฆฟ์ด ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ด๋‹ค. ํ™•์‹คํžˆ WAS๋‹ต๊ฒŒ ๋‹จ์ˆœํ•œ ์›น ์„œ๋ฒ„์™€๋Š” ๋‹ฌ๋ฆฌ ๋กœ์ง์„ ๋ณด๊ด€ํ•œ๋‹ค.

HttpServletRequest

์ด์ œ ์ข€ ๋” ๋””ํ…Œ์ผํ•˜๊ฒŒ ์„œ๋ธ”๋ฆฟ์˜ ์š”์†Œ๋ฅผ ์‚ดํŽด๋ณด์ž. ๋จผ์ € HttpServletRequest์ด๋‹ค. ์„œ๋ธ”๋ฆฟ์€ ๊ฐœ๋ฐœ์ž ๋Œ€์‹  http request message๋ฅผ ํŒŒ์‹ฑํ•ด์„œ ์œ„ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  service ๋ฉ”์„œ๋“œ์˜ ์ธ์ž๋กœ ๋„ฃ์–ด์ค€๋‹ค.

๊ตฌ์ฒด์ ์œผ๋กœ ์ œ๊ณตํ•ด์ค„ ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  • HTTP ๋ฉ”์†Œ๋“œ(GET, POST, DELETE, PUT, โ€ฆ)
  • URL
  • query string
  • ์Šคํ‚ค๋งˆ
  • ํ”„๋กœํ† ์ฝœ ํ—ค๋”
  • form ํŒŒ๋ผ๋ฏธํ„ฐ ํ˜•์‹ ์กฐํšŒ
  • message body ๋ฐ์ดํ„ฐ ์ง์ ‘ ์กฐํšŒ

์ด๊ฒƒ๋งŒ์œผ๋กœ๋Š” ์žฌ๋ฏธ๊ฐ€ ์—†๋‹ค. ํŒŒ์‹ฑ์ •๋„๋Š” ์‹œ์‹œํ•˜์ง€ ์•Š๊ฒ ๋Š”๊ฐ€? ๋ถ€๊ฐ€์ ์ธ ๊ธฐ๋Šฅ์„ ์•„๋ž˜์™€ ๊ฐ™์ด ์ œ๊ณตํ•œ๋‹ค.

  • ์ž„์‹œ ์ €์žฅ์†Œ ๊ธฐ๋Šฅ
    ํ•ด๋‹น HTTP ์š”์ฒญ์ด ์‹œ์ž‘๋ถ€ํ„ฐ ๋๋‚  ๋•Œ ๊นŒ์ง€ ์œ ์ง€๋˜๋Š” ์ž„์‹œ ์ €์žฅ์†Œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ๋‚˜์ค‘์—๋„ ํ•ต์‹ฌ์ ์œผ๋กœ ์“ฐ๊ฒŒ๋˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ˆ ๊ธฐ์–ตํ•ด๋‘์ž.
request.setAttribute(name, value)  
request.getAttribute(name)  
  • ์„ธ์…˜ ๊ด€๋ฆฌ ๊ธฐ๋Šฅ
request.getSession(create: true)  

์ด๋ ‡๊ฒŒ HttpRequest์— ๋Œ€ํ•œ ๋Œ€๋ถ€๋ถ„์˜ ์ •๋ณด๋ฅผ API๋ฅผ ํ†ตํ•ด ์–ป์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค. ์Šคํ”„๋ง์—์„œ๋„ ํ•„์š”์‹œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํ•„์š”ํ• ๋•Œ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ์ฐพ์•„๋ณด๋„๋ก ํ•˜์ž.

Jackson ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
์Šคํ”„๋ง์—์„œ๋Š” ํ•„์š”์—†์ง€๋งŒ ๊ฐ€๋” ๋ณด์ด๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ผ์„œ ์ •๋ฆฌํ•ด๋ณธ๋‹ค. ๋งˆ์น˜ node.js์™€ javascript๊ฐ„์— ๊ทธ๋Ÿฌํ•˜๋“ฏ์ด JSON ํ˜•์‹์„ ๋ฐ›์•„์„œ ๋ฐ”๋กœ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ์Šคํ”„๋ง์—์„œ๋Š” ๊ธฐ๋ƒฅ ๋œ๋‹ค.

POST http://localhost:8080/request-body-json
content-type: application/json
message body:
{โ€œusernameโ€: โ€œhelloโ€, โ€œageโ€: 20} ๊ฒฐ๊ณผ: messageBody = {โ€œusernameโ€: โ€œhelloโ€, โ€œageโ€: 20}

  @Getter @Setter  
  public class HelloData {  
      private String username;  
      private int age;  
  }  
  
import com.fasterxml.jackson.databind.ObjectMapper;  
// ์ด ๋…€์„์ด json์„ object๋กœ ๋งคํ•‘ํ•ด์ค€๋‹ค.  
  
  
@WebServlet(name = "requestBodyJsonServlet", urlPatterns = "/request-body-  
    json")  
    public class RequestBodyJsonServlet extends HttpServlet {  
        private ObjectMapper objectMapper = new ObjectMapper();  
@Override  
        protected void service(HttpServletRequest request, HttpServletResponse  
    response)  
                throws ServletException, IOException {  
            ServletInputStream inputStream = request.getInputStream();  
String messageBody = StreamUtils.copyToString(inputStream,  
    StandardCharsets.UTF_8);  
            HelloData helloData = objectMapper.readValue(messageBody,  
    HelloData.class);  
            System.out.println("helloData.username = " + helloData.getUsername());  
            System.out.println("helloData.age = " + helloData.getAge());  
            response.getWriter().write("ok");  
        }  
}  

HttpServletResponse

  • HttpServletResponse ์—ญํ• 
  • HTTP ์‘๋‹ต ๋ฉ”์‹œ์ง€ ์ƒ์„ฑ HTTP ์‘๋‹ต์ฝ”๋“œ ์ง€์ • ํ—ค๋” ์ƒ์„ฑ
  • ๋ฐ”๋”” ์ƒ์„ฑ
  • ํŽธ์˜ ๊ธฐ๋Šฅ ์ œ๊ณต
  • Content-Type, ์ฟ ํ‚ค, Redirect

request์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ response๋„ ํŽธ์˜๊ธฐ๋Šฅ์„ ๋งŽ์ด ์ œ๊ณตํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์—ญ์‹œ๋‚˜ ์Šคํ”„๋ง์—์„œ๋Š” ๋” ํŽธํ•˜๊ฒŒ ์ œ๊ณตํ•œ๋‹ค.

Response์˜ ํ—ค๋”๋Š” ์ €๋ ‡๊ฒŒ ์ž‘์„ฑํ•œ๋‹ค ์น˜๊ณ , ์ด์ œ response ๋ฉ”์‹œ์ง€์˜ body๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž. ์š”์ฆ˜์€ rest api๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ํ”„๋ก ํŠธ์—”๋“œ๋Š” ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ๊ตฌ์„ฑํ•˜๋Š”๊ฒŒ ์ผ๋ฐ˜์ ์ด์ง€๋งŒ ์˜ˆ์ „์—” ์„œ๋ฒ„์‚ฌ์ด๋“œ ๋ Œ๋”๋ง์ด ์ผ๋ฐ˜์ ์ด์—ˆ๊ณ , ๋”ฐ๋ผ์„œ ์›น ์š”์ฒญ์— ๋Œ€ํ•ด html์„ ๋ฐ˜ํ™˜ํ•  ํ•„์š”๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

@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");  
  
  
// ์ฐธ๊ณ  : ์ฟ ํ‚ค ์ „๋‹ฌํ•˜๋Š”๋ฒ•  
Cookie cookie = new Cookie("myCookie", "good");  
cookie.setMaxAge(600); //600์ดˆ  
      response.addCookie(cookie);  
  
  
// ๋˜์ž‰?  
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์„ ์ง์ ‘ ์ƒ์„ฑํ•ด์„œ response๋กœ ์ „๋‹ฌํ•˜๊ณ  ์žˆ๋‹ค.

์ž๋ฐ” ์ฝ”๋“œ๋กœ HTML์„ ๋งŒ๋“ค์–ด ๋‚ด๋Š” ๊ฒƒ ๋ณด๋‹ค ์ฐจ๋ผ๋ฆฌ HTML ๋ฌธ์„œ์— ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„๋งŒ ์ž๋ฐ” ์ฝ”๋“œ๋ฅผ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋” ํŽธ๋ฆฌํ•  ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์ด ๋ฐ”๋กœ ํ…œํ”Œ๋ฆฟ ์—”์ง„์ด ๋‚˜์˜จ ์ด์œ ์ด๋‹ค. ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์‚ฌ์šฉํ•˜๋ฉด HTML ๋ฌธ์„œ์—์„œ ํ•„์š”ํ•œ ๊ณณ๋งŒ ์ฝ”๋“œ๋ฅผ ์ ์šฉํ•ด์„œ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.
ํ…œํ”Œ๋ฆฟ ์—”์ง„์—๋Š” JSP, Thymeleaf, Freemarker, Velocity๋“ฑ์ด ์žˆ๋‹ค.

JSP

๋ญ”์ง€๋„ ๋ชฐ๋ž๋˜ JSP. ์•Œ๊ณ ๋ณด๋‹ˆ ํ…œํ”Œ๋ฆฟ ์—”์ง„์ด์—ˆ๋‹ค. ๊นจ๋‹ซ๊ณ  ๋‚˜๋‹ˆ ์•„๋ฌด๋„ ์ด์ œ๋Š” ์“ฐ์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜๋„ ์•Œ์•„๋ณด์ž.

๊ทธ๋Ÿฐ๋ฐ, ์ฝ”๋“œ์—์„œ ๋ณด๋“ฏ์ด ์ด๊ฒƒ์€ ๋งค์šฐ ๋ณต์žกํ•˜๊ณ  ๋น„ํšจ์œจ ์ ์ด๋‹ค. ์ž๋ฐ” ์ฝ”๋“œ๋กœ HTML์„ ๋งŒ๋“ค์–ด ๋‚ด๋Š” ๊ฒƒ ๋ณด๋‹ค ์ฐจ๋ผ๋ฆฌ HTML ๋ฌธ์„œ์— ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„๋งŒ ์ž๋ฐ” ์ฝ”๋“œ๋ฅผ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋” ํŽธ๋ฆฌํ•  ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์ด ๋ฐ”๋กœ ํ…œํ”Œ๋ฆฟ ์—”์ง„์ด ๋‚˜์˜จ ์ด์œ ์ด๋‹ค. ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์‚ฌ์šฉํ•˜๋ฉด HTML ๋ฌธ์„œ์—์„œ ํ•„์š”ํ•œ ๊ณณ๋งŒ ์ฝ”๋“œ๋ฅผ ์ ์šฉํ•ด์„œ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.
ํ…œํ”Œ๋ฆฟ ์—”์ง„์—๋Š” JSP, Thymeleaf, Freemarker, Velocity๋“ฑ์ด ์žˆ๋‹ค.

<%@ 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);  
%>  
<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์„ ์ค‘์‹ฌ์œผ๋กœ ํ•˜๊ณ , ์ž๋ฐ”
์ฝ”๋“œ๋ฅผ ๋ถ€๋ถ„๋ถ€๋ถ„ ์ž…๋ ฅํ•ด์ฃผ์—ˆ๋‹ค. <% ~ %> ๋ฅผ ์‚ฌ์šฉํ•ด์„œ HTML ์ค‘๊ฐ„์— ์ž๋ฐ” ์ฝ”๋“œ๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ์žˆ๋‹ค.

<%@ page contentType=โ€text/html;charset=UTF-8โ€ language=โ€javaโ€ %>
์ฒซ ์ค„์€ JSP๋ฌธ์„œ๋ผ๋Š” ๋œป์ด๋‹ค. JSP ๋ฌธ์„œ๋Š” ์ด๋ ‡๊ฒŒ ์‹œ์ž‘ํ•ด์•ผ ํ•œ๋‹ค.

๋‹ค๋ฅธ ํ…œํ”Œ๋ฆฟ์—”์ง„(django template, pug ๊ฐ™์€๊ฒƒ๋„ ๋ดค์œผ๋‹ˆ ๋ญ”์ง€ ๋Œ€์ถฉ ์•Œ๊ฒƒ์ด๋‹ค.

ํšŒ์› ๋“ฑ๋ก ํผ JSP๋ฅผ ๋ณด๋ฉด ์ฒซ ์ค„์„ ์ œ์™ธํ•˜๊ณ ๋Š” ์™„์ „ํžˆ HTML์™€ ๋˜‘๊ฐ™๋‹ค. JSP๋Š” ์„œ๋ฒ„ ๋‚ด๋ถ€์—์„œ ์„œ๋ธ”๋ฆฟ์œผ๋กœ
๋ณ€ํ™˜๋˜๋Š”๋ฐ, ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค์—ˆ๋˜ MemberFormServlet๊ณผ ๊ฑฐ์˜ ๋น„์Šทํ•œ ๋ชจ์Šต์œผ๋กœ ๋ณ€ํ™˜๋œ๋‹ค.

์‹คํ–‰
http://localhost:8080/jsp/members/new-form.jsp
์‹คํ–‰์‹œ .jsp ๊นŒ์ง€ ํ•จ๊ป˜ ์ ์–ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

์ฆ‰, ๋‹จ์ˆœ html์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์„œ๋ธ”๋ฆฟ์ด๋ผ๋ฉด ์„œ๋ธ”๋ฆฟ์„ ์ž‘์„ฑํ•  ํ•„์š”์—†์ด jsp๋งŒ ์ž‘์„ฑํ•˜๋ฉด ๊ทธ url๋กฒ์ ‘์†์‹œ ๋™์ผํ•œ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์ด์•ผ๊ธฐ์ด๋‹ค.

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

์„œ๋ธ”๋ฆฟ๊ณผ JSP์˜ ํ•œ๊ณ„
์„œ๋ธ”๋ฆฟ์œผ๋กœ ๊ฐœ๋ฐœํ•  ๋•Œ๋Š” ๋ทฐ(View)ํ™”๋ฉด์„ ์œ„ํ•œ HTML์„ ๋งŒ๋“œ๋Š” ์ž‘์—…์ด ์ž๋ฐ” ์ฝ”๋“œ์— ์„ž์—ฌ์„œ ์ง€์ €๋ถ„ํ•˜๊ณ  ๋ณต์žกํ–ˆ๋‹ค.
JSP๋ฅผ ์‚ฌ์šฉํ•œ ๋•๋ถ„์— ๋ทฐ๋ฅผ ์ƒ์„ฑํ•˜๋Š” HTML ์ž‘์—…์„ ๊น”๋”ํ•˜๊ฒŒ ๊ฐ€์ ธ๊ฐ€๊ณ , ์ค‘๊ฐ„์ค‘๊ฐ„ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์—๋งŒ ์ž๋ฐ” ์ฝ”๋“œ๋ฅผ ์ ์šฉํ–ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ด๋ ‡๊ฒŒ ํ•ด๋„ ํ•ด๊ฒฐ๋˜์ง€ ์•Š๋Š” ๋ช‡๊ฐ€์ง€ ๊ณ ๋ฏผ์ด ๋‚จ๋Š”๋‹ค.
ํšŒ์› ์ €์žฅ JSP๋ฅผ ๋ณด์ž. ์ฝ”๋“œ์˜ ์ƒ์œ„ ์ ˆ๋ฐ˜์€ ํšŒ์›์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด๊ณ , ๋‚˜๋จธ์ง€ ํ•˜์œ„ ์ ˆ๋ฐ˜๋งŒ ๊ฒฐ๊ณผ๋ฅผ HTML๋กœ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•œ ๋ทฐ ์˜์—ญ์ด๋‹ค. ํšŒ์› ๋ชฉ๋ก์˜ ๊ฒฝ์šฐ์—๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋‹ค.

์ฝ”๋“œ๋ฅผ ์ž˜ ๋ณด๋ฉด, JAVA ์ฝ”๋“œ, ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๋“ฑ๋“ฑ ๋‹ค์–‘ํ•œ ์ฝ”๋“œ๊ฐ€ ๋ชจ๋‘ JSP์— ๋…ธ์ถœ๋˜์–ด ์žˆ๋‹ค. JSP๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์€ ์—ญํ• ์„ ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ์ž‘์€ ํ”„๋กœ์ ํŠธ๋„ ๋ฒŒ์จ ๋จธ๋ฆฌ๊ฐ€ ์•„ํŒŒ์˜ค๋Š”๋ฐ, ์ˆ˜๋ฐฑ ์ˆ˜์ฒœ์ค„์ด ๋„˜์–ด๊ฐ€๋Š” JSP๋ฅผ ๋– ์˜ฌ๋ ค๋ณด๋ฉด ์ •๋ง ์ง€์˜ฅ๊ณผ ๊ฐ™์„ ๊ฒƒ์ด๋‹ค. (์œ ์ง€๋ณด์ˆ˜ ์ง€์˜ฅ ์ฐ)

MVC ํŒจํ„ด์˜ ๋“ฑ์žฅ
๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ์„œ๋ธ”๋ฆฟ ์ฒ˜๋Ÿผ ๋‹ค๋ฅธ๊ณณ์—์„œ ์ฒ˜๋ฆฌํ•˜๊ณ , JSP๋Š” ๋ชฉ์ ์— ๋งž๊ฒŒ HTML๋กœ ํ™”๋ฉด(View)์„ ๊ทธ๋ฆฌ๋Š” ์ผ์— ์ง‘์ค‘ํ•˜๋„๋ก ํ•˜์ž. ๊ณผ๊ฑฐ ๊ฐœ๋ฐœ์ž๋“ค๋„ ๋ชจ๋‘ ๋น„์Šทํ•œ ๊ณ ๋ฏผ์ด ์žˆ์—ˆ๊ณ , ๊ทธ๋ž˜์„œ MVC ํŒจํ„ด์ด ๋“ฑ์žฅํ–ˆ๋‹ค. ์šฐ๋ฆฌ๋„ ์ง์ ‘ MVC ํŒจํ„ด์„ ์ ์šฉํ•ด์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ๋ฆฌํŒฉํ„ฐ๋ง ํ•ด๋ณด์ž.

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

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

์ฐธ๊ณ 

์ปจํŠธ๋กค๋Ÿฌ์— ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋‘˜ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์€ ์—ญํ• ์„ ๋‹ด๋‹นํ•œ๋‹ค. ๊ทธ๋ž˜์„œ
์ผ๋ฐ˜์ ์œผ๋กœ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ์„œ๋น„์Šค(Service)๋ผ๋Š” ๊ณ„์ธต์„ ๋ณ„๋„๋กœ ๋งŒ๋“ค์–ด์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ปจํŠธ๋กค๋Ÿฌ๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์žˆ๋Š” ์„œ๋น„์Šค๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋‹ด๋‹นํ•œ๋‹ค. ์ฐธ๊ณ ๋กœ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋ณ€๊ฒฝํ•˜๋ฉด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ํ˜ธ์ถœํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ์˜ ์ฝ”๋“œ๋„ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋‹ค. ์•ž์—์„œ๋Š” ์ดํ•ด๋ฅผ ๋•๊ธฐ ์œ„ํ•ด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ํ˜ธ์ถœํ•œ๋‹ค๋Š” ํ‘œํ˜„ ๋ณด๋‹ค๋Š”, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด๋ผ ์„ค๋ช…ํ–ˆ๋‹ค.

์ ์šฉ

@WebServlet(name = "mvcMemberSaveServlet", urlPatterns = "/servlet-mvc/members/  
    save")  
    public class MvcMemberSaveServlet extends HttpServlet {  
        private MemberRepository memberRepository = MemberRepository.getInstance();  
@Override  
        protected void service(HttpServletRequest request, HttpServletResponse  
    response)  
                throws ServletException, IOException {  
            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);  
  
//Model์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๊ด€ํ•œ๋‹ค.  
request.setAttribute("member", member);  
  
          String viewPath = "/WEB-INF/views/save-result.jsp";  
          RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);  
          dispatcher.forward(request, response);  
} }   

dispatcher.forward() : ๋‹ค๋ฅธ ์„œ๋ธ”๋ฆฟ์ด๋‚˜ JSP๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค. ์„œ๋ฒ„ ๋‚ด๋ถ€์—์„œ ๋‹ค์‹œ ํ˜ธ์ถœ์ด

๋ฐœ์ƒํ•œ๋‹ค.

/WEB-INF
์ด ๊ฒฝ๋กœ์•ˆ์— JSP๊ฐ€ ์žˆ์œผ๋ฉด ์™ธ๋ถ€์—์„œ ์ง์ ‘ JSP๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๊ธฐ๋Œ€ํ•˜๋Š” ๊ฒƒ์€ ํ•ญ์ƒ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ
ํ†ตํ•ด์„œ JSP๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
redirect vs forward
๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋Š” ์‹ค์ œ ํด๋ผ์ด์–ธํŠธ(์›น ๋ธŒ๋ผ์šฐ์ €)์— ์‘๋‹ต์ด ๋‚˜๊ฐ”๋‹ค๊ฐ€, ํด๋ผ์ด์–ธํŠธ๊ฐ€ redirect ๊ฒฝ๋กœ๋กœ ๋‹ค์‹œ
์š”์ฒญํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ธ์ง€ํ•  ์ˆ˜ ์žˆ๊ณ , URL ๊ฒฝ๋กœ๋„ ์‹ค์ œ๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค. ๋ฐ˜๋ฉด์— ํฌ์›Œ๋“œ๋Š” ์„œ๋ฒ„ ๋‚ด๋ถ€์—์„œ ์ผ์–ด๋‚˜๋Š” ํ˜ธ์ถœ์ด๊ธฐ ๋•Œ๋ฌธ์— ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ „ํ˜€ ์ธ์ง€ํ•˜์ง€ ๋ชปํ•œ๋‹ค.

View

<%@ 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>  

<%= request.getAttribute(โ€œmemberโ€)%> ๋กœ ๋ชจ๋ธ์— ์ €์žฅํ•œ member ๊ฐ์ฒด๋ฅผ ๊บผ๋‚ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋„ˆ๋ฌด ๋ณต์žกํ•ด์ง„๋‹ค.
JSP๋Š” ${} ๋ฌธ๋ฒ•์„ ์ œ๊ณตํ•˜๋Š”๋ฐ, ์ด ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด request์˜ attribute์— ๋‹ด๊ธด ๋ฐ์ดํ„ฐ๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.