๊ด€๋ฆฌ ๋ฉ”๋‰ด

C-log

3week - MVC ๋ณธ๋ฌธ

๐Ÿ“•JAVA/Spring

3week - MVC

4:Bee 2024. 3. 20. 13:49
728x90

* ๋Œ€๋ฉด ์ˆ˜์—… ๋‚ด์šฉ

๋”๋ณด๊ธฐ

model 

view

controller

dispatcher servlet

contextloadlistener

Maven์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ์™€ ์žฅ์ 

* ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ์•Œ์•„์•ผํ•œ๋‹ค.


# MVC ์ƒ์„ฑ(Controller&View)

### pom.xml์€ ๋ฌด์—‡์ธ๊ฐ€

* HomeController.java

package kr.ac.hansung.cse.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;

@Controller
public class HomeController {

    //private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
    private static final Logger logger = LoggerFactory.getLogger("kr.ac.hansung.controller.HomeController");


//    @RequestMapping(value = "/", method = RequestMethod.GET)
    @GetMapping("/")
    public String home(HttpServletRequest request) {

        String url = request.getRequestURL().toString();
        String clientIPaddr = request.getRemoteAddr();

        logger.info("Request URL: {}, Client IP: {}", url, clientIPaddr);

        return "home";
    }
}


์œ„์˜ ์ฝ”๋“œ๋Š” ์Šคํ”„๋ง MVC ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํ™ˆ ํŽ˜์ด์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ์ž…๋‹ˆ๋‹ค. ๊ฐ ๋ถ€๋ถ„์— ๋Œ€ํ•œ ์„ค๋ช…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

* @Controller - ์–ด๋…ธํ…Œ์ด์…˜
ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ์Šคํ”„๋ง MVC์˜ ์ปจํŠธ๋กค๋Ÿฌ์ž„์„ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์ด๋Š” ์ถ”ํ›„์— appServlet์—์„œ Controller ํด๋ž˜์Šค๋ฅผ ํƒ์ƒ‰ํ•  ๋•Œ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•œ๋‹ค.

* @GetMapping("/") - ์–ด๋…ธํ…Œ์ด์…˜ ?
HTTP GET ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •ํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” "/" ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜ค๋Š” GET ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

* HttpServletRequest request
ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์š”์ฒญ์„ ๋ฐ›์•„๋“ค์ด๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์š”์ฒญ URL๊ณผ ํด๋ผ์ด์–ธํŠธ์˜ IP ์ฃผ์†Œ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.

* Logger logger
๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•˜๊ธฐ ์œ„ํ•œ Logger ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” SLF4J ๋กœ๊น… API๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.

* logger.info("Request URL: {}, Client IP: {}", url, clientIPaddr)
๋กœ๊ทธ์— ์š”์ฒญ URL๊ณผ ํด๋ผ์ด์–ธํŠธ IP ์ฃผ์†Œ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

* return "home";
"home"์ด๋ผ๋Š” ๋ทฐ ์ด๋ฆ„์„ ๋ฐ˜ํ™˜ํ•˜์—ฌ ํ•ด๋‹น ๋ทฐ๋ฅผ ํ‘œ์‹œํ•œ๋‹ค. ์Šคํ”„๋ง MVC๋Š” ์ด ๋ทฐ ์ด๋ฆ„์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์‹ค์ œ ๋ทฐ ํŒŒ์ผ์„ ์ฐพ์•„ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ์ด ์ปจํŠธ๋กค๋Ÿฌ๋Š” "/" ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜ค๋Š” GET ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ์š”์ฒญ URL๊ณผ ํด๋ผ์ด์–ธํŠธ์˜ IP ์ฃผ์†Œ๋ฅผ ๋กœ๊ทธ์— ์ถœ๋ ฅํ•œ ํ›„, "home"์ด๋ผ๋Š” ๋ทฐ๋ฅผ ํ‘œ์‹œํ•œ๋‹ค. ์•„๋ž˜ ์ฝ”๋“œ๋Š” ๋ฐ˜ํ™˜๋œ home ๋ทฐ์— ํ•ด๋‹น๋˜๋Š” jsp์ด๋‹ค. jsp๋Š” ํฌ๊ฒŒ ์–ด๋ ค์›€์ด ์—†๊ธฐ์— ํŒจ์Šค ํ•˜๋„๋ก ํ•˜์ž.

* home.jsp

<%--
  Created by IntelliJ IDEA.
  User: nykim
  Date: 2022/12/13
  Time: 12:55 ์˜ค์ „
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <p><a href="${pageContext.request.contextPath}/offers"/>Show Current offers</p>
  </body>
</html>

* helloSpring-1.0-SNAPSHOT.war

helloSpring-1.0-SNAPSHOT.war ํŒŒ์ผ์€ Maven ๋˜๋Š” Gradle๊ณผ ๊ฐ™์€ ๋นŒ๋“œ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑ๋œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„์นด์ด๋ธŒ(WAR) ํŒŒ์ผ์ด๋‹ค. ์ด ํŒŒ์ผ์€ ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ ๋˜๋Š” ๋‹ค๋ฅธ ์›น ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐœ๋ฐœํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฐฐํฌ๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.

## ์ง€๊ธˆ๊นŒ์ง€์˜ ํŒจํ‚ค์ง€ ํŒŒ์ผ ๊ตฌ์กฐ

์ง€๊ธˆ๊นŒ์ง€ ํŒŒ์ผ์˜ ๊ตฌ์กฐ๋ฅผ ์‚ดํŽด๋ณด๋ฉด controller ํŒจํ‚ค์ง€ ํŒŒ์ผ๊ณผ dao ํŒจํ‚ค์ง€ ํŒŒ์ผ ๋งˆ์ง€๋ง‰์œผ๋กœ service ํŒจํ‚ค์ง€ ํŒŒ์ผ๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ตฌ์กฐ๋Š” ์•„๋ž˜ ์ด๋ฏธ์ง€์™€ ๊ฐ™์ด ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค.

์ง€๊ธˆ๊นŒ์ง€์˜ ํŒŒ์ผ ๊ตฌ์กฐ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ๊ฐ๊ฐ์˜ ์ฑ…์ž„์„ ๋ถ„๋ช…ํžˆ ํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ตฌ์กฐ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜์™€ ํ™•์žฅ์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ๋ฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•œ๋‹ค. ์ด์˜ ๊ตฌ์ฒด์ ์ธ ์„ค๋ช…์€ ์•„๋ž˜ appServlet์„ ํ†ตํ•ด ์„ค๋ช…ํ•˜๊ฒ ๋‹ค.


appServlet ์„ค์ • ํŒŒ์ผ์€ ์ฃผ๋กœ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ”„๋ก ํŠธ ์ปจํŠธ๋กค๋Ÿฌ์ธ DispatcherServlet์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋ฉฐ ์ด๋Š” ์›น ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ๋ผ์šฐํŒ…ํ•˜๋Š” ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. 

* appServlet : servlet-context.xml, doa-context.xml, service-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:context="http://www.springframework.org/schema/context"
             xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <context:component-scan base-package="kr.ac.hansung.cse.controller" />

</beans:beans>
<context:component-scan base-package="kr.ac.hansung.cse.controller" />
@Controller
public class HomeController {
...

servlet-context.xml ์ฝ”๋“œ๋Š” Spring MVC ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ค์ •์„ ๋‹ด๊ณ  ์žˆ์œผ๋ฉฐ ์—ฌ๊ธฐ์„œ <context:component-scan base-package="kr.ac.hansung.cse.controller" /> ๋ถ€๋ถ„์ด ํ•ต์‹ฌ์ ์ธ ์—ญํ• ์„ ํ•œ๋‹ค. <context:component-scan> ํƒœ๊ทธ๋Š” Spring Framework์—๊ฒŒ ์ง€์ •๋œ controller ํŒจํ‚ค์ง€ ๋‚ด์—์„œ ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํด๋ž˜์Šค๋ฅผ ์Šค์บ”ํ•˜๋„๋ก ์ง€์‹œํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ํด๋ž˜์Šค๋“ค์„ Spring์˜ ApplicationContext์— ๋นˆ(Bean)์œผ๋กœ ๋“ฑ๋กํ•˜๊ฒŒ ๋œ๋‹ค. ์ด๋ ‡๊ฒŒ ์›น ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” controller๋กœ ์ธ์‹๋˜์–ด ํ•ด๋‹น ์ปจํŠธ๋กค๋Ÿฌ์˜ ๋ฉ”์„œ๋“œ๋“ค์ด ์›น ์š”์ฒญ์— ์‘๋‹ตํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

### dispatch๋ž€?

๋”๋ณด๊ธฐ

### Servlet์ด๋ž€?

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

### dispatchServlet์ด๋ž€?

DispatcherServlet์€ ์Šคํ”„๋ง MVC(๋ชจ๋ธ-๋ทฐ-์ปจํŠธ๋กค๋Ÿฌ) ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์ค‘์‹ฌ์ ์ธ ์—ญํ• ์„ ํ•˜๋Š” ์„œ๋ธ”๋ฆฟ์œผ๋กœ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค. ์Šคํ”„๋ง ์›น MVC์˜ ํ”„๋ก ํŠธ ์ปจํŠธ๋กค๋Ÿฌ๋กœ์„œ DispatcherServlet์€ ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์š”์ฒญ์„ ์ ์ ˆํ•œ ํ•ธ๋“ค๋Ÿฌ ๋˜๋Š ์ปจํŠธ๋กค๋Ÿฌ์— ์ „๋‹ฌํ•˜๊ณ  ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฐ˜ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

* root-context.xml์€ ์ œ๊ฑฐ

root-context.xml ํŒŒ์ผ์€ ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ตœ๊ทผ์˜ ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ ๋ฒ„์ „์—์„œ๋Š” root-context.xml์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  Java ๊ธฐ๋ฐ˜์˜ ์„ค์ • ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค. Java ๊ธฐ๋ฐ˜์˜ ์„ค์ • ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด XML ํŒŒ์ผ๋ณด๋‹ค ์œ ์—ฐํ•˜๊ณ  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ์„ค์ •์„ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

* web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- The definition of the Root Spring Container shared by all Servlets
        and Filters -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/appServlet/service-context.xml
            /WEB-INF/spring/appServlet/doa-context.xml
        </param-value>
    </context-param>

    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Processes application requests -->
    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

์œ„์˜ XML ํŒŒ์ผ์€ ์Šคํ”„๋ง MVC ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ web.xml ์„ค์ • ํŒŒ์ผ์ด๋‹ค. ์ด ํŒŒ์ผ์€ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฐฐ์น˜ ๋ฐ ์ดˆ๊ธฐํ™”๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ๊ฐ ์š”์†Œ์˜ ์—ญํ• ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค

* web-app
์ด ์š”์†Œ๋Š” ์ด XML ํŒŒ์ผ์ด ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ค์ • ํŒŒ์ผ์ž„์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

* context-param
์ด ์š”์†Œ๋Š” ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” contextConfigLocation์ด๋ผ๋Š” ์ปจํ…์ŠคํŠธ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ค์ •ํ•˜์—ฌ service-context.xml ๋ฐ dao-context.xml ํŒŒ์ผ์„ ์ง€์ •ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

* listener
ContextLoaderListener ํด๋ž˜์Šค๋ฅผ ๋“ฑ๋กํ•˜์—ฌ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

* servlet
์ด ์š”์†Œ๋Š” ์Šคํ”„๋ง MVC ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„œ๋ธ”๋ฆฟ์„ ์„ค์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” DispatcherServlet์„ ๋“ฑ๋กํ•˜๊ณ  servlet-context.xml ํŒŒ์ผ์„ ๋กœ๋“œํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

* servlet-mapping
์„œ๋ธ”๋ฆฟ ๋งคํ•‘์„ ์„ค์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ์ด ๊ฒฝ์šฐ / ๊ฒฝ๋กœ์— ๋Œ€ํ•œ ๋ชจ๋“  ์š”์ฒญ์„ appServlet ์„œ๋ธ”๋ฆฟ์— ๋งคํ•‘ํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์Šคํ”„๋ง MVC ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ดˆ๊ธฐํ™”๋˜๊ณ  ์„ค์ •๋˜๋ฉฐ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ค€๋น„๊ฐ€ ์™„๋ฃŒ๋œ๋‹ค.

์ง€๊ธˆ๊นŒ์ง€์˜ ํด๋” ํŒŒ์ผ ๊ตฌ์„ฑ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.


# MVC ๊ตฌํ˜„(Model&Controller&View)

๋ชจ๋ธ๊ตฌํ˜„

* Offer.java

package kr.ac.hansung.cse.model;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
@NoArgsConstructor

public class Offer {
    private int id;
    private String name;
    private String email;
    private String text;
}

์œ„์˜ ์ฝ”๋“œ๋Š” Java ํด๋ž˜์Šค์ธ Offer๋ฅผ ์ •์˜ํ•˜๊ณ  ์žˆ๋‹ค. ์ด ํด๋ž˜์Šค๋Š” ์ฃผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋‚˜ ์‚ฌ์šฉ์ž ์ž…๋ ฅ๊ณผ ๊ฐ™์€ ์™ธ๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค. ๊ฐ ์–ด๋…ธํ…Œ์ด์…˜๋“ค์„ ์ฃผ์˜๊นŠ๊ฒŒ ์‚ดํŽด๋ณด์ž

* @Getter
Lombok ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ์ž๋™์œผ๋กœ ํ•„๋“œ์— ๋Œ€ํ•œ getter ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ด๊ฒƒ์€ id, name, email, text ํ•„๋“œ์— ๋Œ€ํ•œ getter ๋ฉ”์„œ๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•œ๋‹ค.

* @Setter
Lombok ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ์ž๋™์œผ๋กœ ํ•„๋“œ์— ๋Œ€ํ•œ setter ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ด๊ฒƒ์€ id, name, email, text ํ•„๋“œ์— ๋Œ€ํ•œ setter ๋ฉ”์„œ๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•œ๋‹ค.

* @ToString
Lombok ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ์ž๋™์œผ๋กœ toString() ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ๊ฐ์ฒด์˜ ํ•„๋“œ ๊ฐ’์„ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

* @NoArgsConstructor
Lombok ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ์ธ์ž๋ฅผ ๋ฐ›์ง€ ์•Š๋Š” ๊ธฐ๋ณธ ์ƒ์„ฑ์ž๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•œ๋‹ค.

* private int id
Offer ๊ฐ์ฒด์˜ id๋ฅผ ์ €์žฅํ•˜๋Š” ํ•„๋“œ์ด๋‹ค.

* private String name
Offer ๊ฐ์ฒด์˜ ์ด๋ฆ„์„ ์ €์žฅํ•˜๋Š” ํ•„๋“œ์ด๋‹ค.

* private String email
Offer ๊ฐ์ฒด์˜ ์ด๋ฉ”์ผ ์ฃผ์†Œ๋ฅผ ์ €์žฅํ•˜๋Š” ํ•„๋“œ์ด๋‹ค.

* private String text
Offer ๊ฐ์ฒด์˜ ํ…์ŠคํŠธ๋ฅผ ์ €์žฅํ•˜๋Š” ํ•„๋“œ์ด๋‹ค.

์ด ํด๋ž˜์Šค์˜ ์—ญํ• ์€ ์ฃผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œํ˜„ํ•˜๊ณ  ์ €์žฅํ•˜๋Š” ๋ฐ์— ์žˆ๋‹ค. ์ด ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์˜ ๋ ˆ์ฝ”๋“œ๋ฅผ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๊ณ  ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํผ ๋ฐ์ดํ„ฐ๋ฅผ ๋‚˜ํƒ€๋‚ผ ์ˆ˜๋„ ์žˆ๋‹ค. Getter์™€ Setter ๋ฉ”์„œ๋“œ๋Š” ํ•„๋“œ์— ์ ‘๊ทผํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์„ค์ •ํ•˜๊ฑฐ๋‚˜ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๊ณ  toString() ๋ฉ”์„œ๋“œ๋Š” ๊ฐ์ฒด๋ฅผ ๋ฌธ์ž์—ด๋กœ ํ‘œํ˜„ํ•˜์—ฌ ๋กœ๊น… ๋ฐ ๋””๋ฒ„๊น… ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค.

* OfferController.java

package kr.ac.hansung.cse.controller;

import kr.ac.hansung.cse.model.Offer;
import kr.ac.hansung.cse.service.OfferService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;

@Controller
public class OfferController {
    @Autowired
    private OfferService offerService;
    //offerDao๋กœ ๋ถ€ํ„ฐ mysql๋“ค์„ ์กฐ์ž‘ ์ปจํŠธ๋กค ํ•œ๋‹ค.
    @GetMapping("/offers")
    public String showOffer(Model model){
        List<Offer> offers = offerService.getAllOffers();
        model.addAttribute("id_offers", offers);

        return "offers";
    }
}

์œ„์˜ ์ฝ”๋“œ๋Š” ์Šคํ”„๋ง MVC ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ Offer ๊ฐ์ฒด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ์ธ OfferController๋ฅผ ์ •์˜ํ•˜๊ณ  ์žˆ๋‹ค. ์ด ์ปจํŠธ๋กค๋Ÿฌ์˜ ์—ญํ• ๊ณผ ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•ด๋ณด์ž.

* @Controller
ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ์Šคํ”„๋ง MVC์˜ ์ปจํŠธ๋กค๋Ÿฌ์ž„์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

* @Autowired private OfferService offerService;
OfferService ํƒ€์ž…์˜ ๋นˆ์„ ์ž๋™์œผ๋กœ ์ฃผ์ž…๋ฐ›๋Š”๋‹ค. ์ด๊ฒƒ์€ ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜ํ•ด OfferService์˜ ๊ตฌํ˜„์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  offerService ํ•„๋“œ์— ์ฃผ์ž…๋œ๋‹ค.

* @GetMapping("/offers")
HTTP GET ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •ํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” "/offers" ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜ค๋Š” GET ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

* public String showOffer(Model model)
Model ๊ฐ์ฒด๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค. ์ด ๋ชจ๋ธ ๊ฐ์ฒด๋Š” ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ทฐ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

* List<Offer> offers = offerService.getAllOffers();
offerService๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  Offer ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. ์ด๋Š” ์„œ๋น„์Šค ๊ณ„์ธต์— ์žˆ๋Š” OfferService ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋‚˜ ๋‹ค๋ฅธ ๊ณณ์—์„œ Offer ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

* model.addAttribute("id_offers", offers);
๋ชจ๋ธ์— "id_offers"๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ Offer ๋ชฉ๋ก์„ ์ถ”๊ฐ€ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ทฐ์—์„œ ์ด ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

* return "offers";
"offers"๋ผ๋Š” ๋ทฐ ์ด๋ฆ„์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด๋Š” ์Šคํ”„๋ง MVC๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ์ด ์ด๋ฆ„์„ ๊ฐ€์ง€๋Š” ๋ทฐ๋ฅผ ์ฐพ์•„ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ OfferController๋Š” /offers ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜ค๋Š” GET ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ์ด๋ฅผ ํ†ตํ•ด Offer ๊ฐ์ฒด๋ฅผ ์กฐํšŒํ•˜์—ฌ ๋ทฐ๋กœ ์ „๋‹ฌํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ๋””์ž์ธ์€ MVC (Model-View-Controller) ํŒจํ„ด์„ ๋”ฐ๋ฅด๋ฉฐ ๊ฐ ์š”์†Œ์˜ ์—ญํ• ์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ๋ณด๋‹ค ๊ตฌ์กฐํ™”ํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ ๋‹ค.

* offers.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: rdwoo1024
  Date: 2024-03-27
  Time: ์˜คํ›„ 5:43
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <c:forEach var="offer" items="${id_offers}">
        <p><c:out value="${offer}"></c:out></p>
    </c:forEach>
</body>
</html>

์œ„์˜ ์ฝ”๋“œ๋Š” JSP ํŒŒ์ผ์ธ offer.jsp์ด๋‹ค. ์ด ํŒŒ์ผ์€ Offer ๊ฐ์ฒด์˜ ๋ชฉ๋ก์„ ์ถœ๋ ฅํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•˜๊ณ  ์—ญํ• ์„ ์‚ดํŽด๋ณด์ž.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
JSTL(Core) ํƒœ๊ทธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํƒœ๊ทธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ ์–ธํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด JSP ํŒŒ์ผ์—์„œ JSTL์˜ ์ œ์–ด ๊ตฌ๋ฌธ ๋ฐ ๋ฐ˜๋ณต๋ฌธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
ํ•ด๋‹น JSP ํŽ˜์ด์ง€์˜ ์ฝ˜ํ…์ธ  ์œ ํ˜•์„ HTML๋กœ ์„ค์ •ํ•˜๊ณ  ๋ฌธ์ž ์ธ์ฝ”๋”ฉ์„ UTF-8๋กœ ์„ค์ •ํ•œ๋‹ค.

<c:forEach var="offer" items="${id_offers}">
JSTL์˜ <c:forEach> ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ${id_offers}์— ์žˆ๋Š” ๊ฐ์ฒด๋“ค์„ ๋ฐ˜๋ณตํ•˜๋ฉฐ ์ฒ˜๋ฆฌํ•œ๋‹ค. ${id_offers}๋Š” ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ชจ๋ธ์— ์ถ”๊ฐ€๋œ Offer ๊ฐ์ฒด๋“ค์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

<p><c:out value="${offer}"></c:out></p>
๋ฐ˜๋ณต๋ฌธ ์•ˆ์—์„œ Offer ๊ฐ์ฒด๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ๋ถ€๋ถ„์ด๋‹ค. <c:out> ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ${offer} ๊ฐ’์„ ์ถœ๋ ฅํ•œ๋‹ค. ์ด๋ฅผ <p> ํƒœ๊ทธ๋กœ ๋‘˜๋Ÿฌ์‹ธ์„œ ๊ฐ Offer ๊ฐ์ฒด๋ฅผ ๋‹จ๋ฝ์œผ๋กœ ๋‚˜ํƒ€๋‚ธ๋‹ค.

<title>Title</title>
HTML ๋ฌธ์„œ์˜ ์ œ๋ชฉ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ถ€๋ถ„์ด๋‹ค.

<body>
HTML ๋ฌธ์„œ์˜ ๋ณธ๋ฌธ์„ ์‹œ์ž‘ํ•˜๋Š” ํƒœ๊ทธ์ด๋‹ค.

<html>, <head>, <body>
HTML ๋ฌธ์„œ์˜ ๊ตฌ์กฐ๋ฅผ ์ •์˜ํ•˜๋Š” ํƒœ๊ทธ์ด๋‹ค.

๋”ฐ๋ผ์„œ offer.jsp ํŒŒ์ผ์€ Offer ๊ฐ์ฒด ๋ชฉ๋ก์„ ๋ฐ˜๋ณตํ•˜์—ฌ ์ถœ๋ ฅํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด Offer ๊ฐ์ฒด์˜ ์ •๋ณด๋ฅผ ์›น ํŽ˜์ด์ง€ ์ƒ์— ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค

* OfferService.java

package kr.ac.hansung.cse.service;

import kr.ac.hansung.cse.dao.OfferDao;
import kr.ac.hansung.cse.model.Offer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class OfferService {
    @Autowired
    private OfferDao offerDao;
    public List<Offer> getAllOffers(){
        return offerDao.getOffers();
    }
}

์œ„์˜ ์ฝ”๋“œ๋Š” OfferService๋ผ๋Š” ์„œ๋น„์Šค ํด๋ž˜์Šค์ด๋‹ค. ์ด ํด๋ž˜์Šค๋Š” ์ฃผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜์—ฌ Offer ๊ฐ์ฒด์— ๋Œ€ํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•œ๋‹ค. ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•˜๊ณ  ์—ญํ• ์„ ์„ค๋ช…ํ•ด๋ณด๊ฒ ํ•œ๋‹ค

@Service
ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ์Šคํ”„๋ง์˜ ์„œ๋น„์Šค๋กœ ์ธ์‹๋˜๋„๋ก ํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด๋‹ค. ์ด๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ  ํ•„์š”ํ•œ ๊ณณ์—์„œ ์ฃผ์ž…ํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

@Autowired private OfferDao offerDao;
OfferDao ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๋นˆ์„ ์ž๋™์œผ๋กœ ์ฃผ์ž…๋ฐ›๋Š”๋‹ค. ์ด๊ฒƒ์€ ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜ํ•ด OfferDao์˜ ๊ตฌํ˜„์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  offerDao ํ•„๋“œ์— ์ฃผ์ž…๋œ๋‹ค.

public List<Offer> getAllOffers()
๋ชจ๋“  Offer ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” DAO ๊ณ„์ธต์— ์žˆ๋Š” OfferDao ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ Offer ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.

return offerDao.getOffers();
OfferDao ๊ฐ์ฒด์˜ getOffers() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋ชจ๋“  Offer ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ Offer ์ •๋ณด๋ฅผ ์กฐํšŒํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ OfferService ํด๋ž˜์Šค๋Š” ์ฃผ๋กœ DAO ๊ณ„์ธต๊ณผ ์ƒํ˜ธ ์ž‘์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ Offer ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์—ญํ• ์„ ํ•œ. ์ด๋ฅผ ํ†ตํ•ด ์ปจํŠธ๋กค๋Ÿฌ๋‚˜ ๋‹ค๋ฅธ ์„œ๋น„์Šค ๊ณ„์ธต์—์„œ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์„œ๋น„์Šค ๊ณ„์ธต์— ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ ์ฝ”๋“œ์˜ ์‘์ง‘์„ฑ์„ ๋†’์ด๊ณ  ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚จ๋‹ค.

*OfferDao.java

package kr.ac.hansung.cse.dao;

import kr.ac.hansung.cse.model.Offer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

@Repository
public class OfferDao {

    private JdbcTemplate jdbcTemplate;  // psa(portable service abstraction, sql(x) api

    @Autowired
    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public int getRowCount() {
        String sqlStatement= "select count(*) from offers";
        return jdbcTemplate.queryForObject(sqlStatement, Integer.class);

    }
    //query and return a single object
    public Offer getOffer(String name) {

        String sqlStatement= "select * from offers where name=?";
        return jdbcTemplate.queryForObject(sqlStatement, new Object[] {name},
                new RowMapper<Offer>() {

                    @Override
                    public Offer mapRow(ResultSet rs, int rowNum) throws SQLException {

                        Offer offer= new Offer();

                        offer.setId(rs.getInt("id"));
                        offer.setName(rs.getString("name"));
                        offer.setEmail(rs.getString("email"));
                        offer.setText(rs.getString("text"));

                        return offer;
                    }
                });
    }

    //query and return multiple objects
    // cRud method
    public List<Offer> getOffers() {

        String sqlStatement= "select * from offers";
        return jdbcTemplate.query(sqlStatement, new RowMapper<Offer>() {

            @Override
            public Offer mapRow(ResultSet rs, int rowNum) throws SQLException {

                Offer offer= new Offer();

                offer.setId(rs.getInt("id"));
                offer.setName(rs.getString("name"));
                offer.setEmail(rs.getString("email"));
                offer.setText(rs.getString("text"));

                return offer;
            }
        });
    }


    // Crud method
    public boolean insert(Offer offer) {

        String name= offer.getName();
        String email= offer.getEmail();
        String text = offer.getText();

        String sqlStatement= "insert into offers (name, email, text) values (?,?,?)";

        return (jdbcTemplate.update(sqlStatement, new Object[] {name, email, text}) == 1);
    }

    // crUd method
    public boolean update(Offer offer) {

        int id = offer.getId();
        String name= offer.getName();
        String email= offer.getEmail();
        String text = offer.getText();

        String sqlStatement= "update offers set name=?, email=?, text=? where id=?";

        return (jdbcTemplate.update(sqlStatement, new Object[] {name, email, text, id}) == 1);
    }

    //cruD method
    public boolean delete(int id) {
        String sqlStatement= "delete from offers where id=?";
        return (jdbcTemplate.update(sqlStatement, new Object[] {id}) == 1);
    }

}

OfferDao ํด๋ž˜์Šค๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•œ DAO(Data Access Object) ํด๋ž˜์Šค๋กœ์„œ, ์ฃผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ CRUD(Create, Read, Update, Delete) ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์ด ํด๋ž˜์Šค๋Š” JDBC(Java Database Connectivity)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค.

@Repository
ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ์Šคํ”„๋ง์˜ ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋˜๋Š” ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ํด๋ž˜์Šค์ž„์„ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์ด๋Š” ์Šคํ”„๋ง์ด ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์„ ํ†ตํ•ด ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ , ํ•„์š”ํ•œ ๊ณณ์—์„œ ์ฃผ์ž…ํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

private JdbcTemplate jdbcTemplate;
JDBC๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•œ JdbcTemplate ๊ฐ์ฒด๋ฅผ ์„ ์–ธํ•œ๋‹ค.

public void setDataSource(DataSource dataSource) { ... }
DataSource ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„์„œ JdbcTemplate ๊ฐ์ฒด๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ์Šคํ”„๋ง์˜ ์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection)์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ์„ค์ •ํ•œ๋‹ค.

public int getRowCount() { ... }
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์˜ ํ–‰ ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค.

public Offer getOffer(String name) { ... }
์ด๋ฆ„์„ ๊ธฐ์ค€์œผ๋กœ ํŠน์ • Offer ๊ฐ์ฒด๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค.

public List<Offer> getOffers() { ... }
๋ชจ๋“  Offer ๊ฐ์ฒด์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค.

public boolean insert(Offer offer) { ... }
์ƒˆ๋กœ์šด Offer ๊ฐ์ฒด๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์‚ฝ์ž…ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค.

public boolean update(Offer offer) { ... }
๊ธฐ์กด์˜ Offer ๊ฐ์ฒด๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค.

public boolean delete(int id) { ... }
ํŠน์ • id๋ฅผ ๊ฐ€์ง„ Offer ๊ฐ์ฒด๋ฅผ ์‚ญ์ œํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค.

์ด๋Ÿฌํ•œ ๋ฉ”์„œ๋“œ๋“ค์„ ํ†ตํ•ด OfferDao ํด๋ž˜์Šค๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ์ถ”์ƒํ™”ํ•˜๊ณ  ์„œ๋น„์Šค๋‚˜ ์ปจํŠธ๋กค๋Ÿฌ ๋“ฑ์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•˜์—ฌ CRUD ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ๋ฐ์ดํ„ฐ ์•ก์„ธ์Šค ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜๊ณ  ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚จ๋‹ค.

# MVC ํ†ตํ•ฉํ…Œ์ŠคํŠธ(MYSQL)

ํ•ด๋‹น ํŒŒํŠธ๋Š” ๊ฐ•์˜๋ฅผ ํ†ตํ•ด ์ •๋ฆฌํ•ด ๋‘๋Š” ๊ฒƒ ๋ณด๋‹จ ๋ณด๋Š” ๊ฒƒ์ด ์‰ฝ๋‹ค. ๋”ฐ๋กœ ์ •๋ฆฌํ•ด ๋‘์ง„ ์•Š์•˜์œผ๋‹ˆ ๊ฐ ๊ฐœ์ธ๋“ค ๋งˆ๋‹ค offfer ํŒŒํŠธ๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ์ž๋ฃŒ๋ฅผ ์ฐพ์•„ ์‹ค์Šต์„ ํ•ด๋ณด๊ธฐ ๋ฐ”๋ž€๋‹ค.


##์ค‘๊ฐ„๊ณ ์‚ฌ๋ฅผ ์œ„ํ•œ  ์ด๋ก  ์ •๋ฆฌ

Controller์™€ View์— ๊ด€ํ•ด์„œ


* Model

Model์€ Controller๊ฐ€ ์ˆ˜ํ–‰ํ•œ ๊ฒฐ๊ณผ๋ฌผ์„ ์ €์žฅํ•˜๋Š” ๊ณณ์ด๋‹ค. Controller๊ฐ€ Model์— ๊ฒฐ๊ณผ๋ฅผ ๋„˜๊ฒจ ์ฃผ๋ฉด View์—์„œ ๊ฒฐ๊ณผ๋ฌผ์„ ๊บผ๋‚ด์„œ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ๋ฐฉ์‹์ด ๋˜๊ฒ ๋‹ค. Model์—์„œ๋Š” POJO๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ์ด ๋œ๋‹ค. Named Object๊ฐ€ ์ง‘ํ•ฉ๋˜์–ด ์žˆ๋Š” ๊ฒƒ์ด Model์ด๋‹ค. (Named Object๋Š” ์Šคํ”„๋ง MVC์˜ Model์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ฐ์ดํ„ฐ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์šฉ์–ด๋กœ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.)

 

* Model์€ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š”๊ฐ€

์„ธ๊ฐ€์ง€๊ฐ€ ์žˆ๋Š”๋ฐ java.util.map, Model, ModelMap ๋ฐฉ์‹์ด ์žˆ๋‹ค.

1. public String getGreeting(Map<String, Object> model ) { ... }

์ด ๋ฐฉ๋ฒ•์€ java.util.Map ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋ธ์„ ์ „๋‹ฌํ•œ๋‹ค. ๋ฉ”์„œ๋“œ ๋‚ด์—์„œ ๋ฐ์ดํ„ฐ๋Š” model ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ถ”๊ฐ€๋œ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ด๊ณ  ๋ฒ”์šฉ์ ์ธ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ ๋ชจ๋ธ์„ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ๋งŽ์€ ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค.

java.util.Map์„ ์‚ฌ์šฉํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค.

์ด ์ฝ”๋“œ๋Š” "/greeting" ์—”๋“œํฌ์ธํŠธ์— ๋งคํ•‘๋œ ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ์„œ๋น„์Šค๋กœ๋ถ€ํ„ฐ "greeting"์„ ๊ฐ€์ ธ์™€์„œ ๋ชจ๋ธ์— "greeting"์ด๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  "home"์ด๋ผ๋Š” ๋ทฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ model.put("greeting", greeting)์€ "greeting"์ด๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ service์—์„œ ๊ฐ€์ ธ์˜จ "greeting"์„ ๋ชจ๋ธ์— ์ถ”๊ฐ€ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ชจ๋ธ์€ ๋ทฐ์— ์ „๋‹ฌ๋˜์–ด ํ™”๋ฉด์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ทฐ์—์„œ๋Š” "greeting"์ด๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ๋ชจ๋ธ์— ์„ค์ •๋œ ๊ฐ’์— ์ ‘๊ทผํ•˜์—ฌ ํ•ด๋‹น "greeting"์„ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. public String getGreeting(Model model ) { ... }

์ด ๋ฐฉ๋ฒ•์€ ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์˜ org.springframework.ui.Model ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋ธ์„ ์ „๋‹ฌํ•œ๋‹ค. ์ด ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ์ฃผ๋กœ ์Šคํ”„๋ง MVC ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

Map์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๊ฐ ๋ชจ๋ธ ์†์„ฑ์˜ ์ด๋ฆ„์„ ๊ฒฐ์ •ํ•ด์•ผ ํ•œ๋‹ค. ์ด๋Š” ์ง€๋ฃจํ•˜๊ณ  ์–ด๋ ค์šด ๊ณผ์ •์ผ ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, "greeting"์ด๋ผ๋Š” ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์—ฌ greeting ๋ณ€์ˆ˜๋ฅผ ๋ชจ๋ธ์— ์ถ”๊ฐ€ํ•œ๋‹ค.

Model ์ธํ„ฐํŽ˜์ด์Šค๋Š” addAttribute()์™€ ๊ฐ™์€ ํŽธ๋ฆฌํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜์—ฌ Model์„ ์ฑ„์šฐ๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. addAttribute()๋Š” Map์˜ put()๊ณผ ๋™์ผํ•˜์ง€๋งŒ ๋ชจ๋ธ ์†์„ฑ์˜ ์ด๋ฆ„์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์—ฌ์ „ํžˆ ๊ฐ ๋ชจ๋ธ ์†์„ฑ์˜ ์ด๋ฆ„์„ ์ˆ˜๋™ ์ ์œผ๋กœ ์ง์ ‘ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ด๋ฆ„์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

Key๊ฐ’์ด ์—†์ด Value๊ฐ’๋งŒ ์กด์žฌํ•˜๋ฉฐ ์ง์ ‘ ์ง‘์–ด ๋„ฃ๋Š” ๋ฐฉ์‹์˜ Model Map์ด๋‹ค. ์›๋ž˜๋ผ๋ฉด value๊ฐ’์„ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•ด์•ผํ•œ๋‹ค.


3. public String getGreeting(ModelMap model ) { ... }

์ด ๋ฐฉ๋ฒ•์€ org.springframework.ui.ModelMap ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋ธ์„ ์ „๋‹ฌํ•œ๋‹ค. ModelMap์€ Model๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ ์ถ”๊ฐ€์ ์ธ ํŽธ์˜ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค. ModelMap์€ ๋‚ด๋ถ€์ ์œผ๋กœ LinkedHashMap์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ง€ํ•˜๋ฏ€๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์ถ”๊ฐ€๋œ ์ˆœ์„œ๋Œ€๋กœ ์œ ์ง€๋œ๋‹ค.

addAttribute Chained Call์„ ํ†ตํ•ด์„œ key์™€ value๊ฐ’์„ ์ƒ์„ฑํ•˜๋Š” Map ๋ฐฉ์‹์ด๋‹ค.
์•ž์„œ ๋งํ–ˆ๋“ฏ์ด Controller์—์„œ ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋ฅผ Model๋กœ ๋„˜๊ฒจ์ฃผ๊ณ  ์ด๋ฅผ View๋กœ ๋„˜๊ฒจ์ฃผ๋Š” ์ฝ”๋“œ์˜ Controller์ด๋‹ค.


* Controller

@Controller annotation

@Controller ์–ด๋…ธํ…Œ์ด์…˜์€ ํด๋ž˜์Šค๊ฐ€ ์ปจํŠธ๋กค๋Ÿฌ ์—ญํ• ์„ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์ด ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ Spring์—๊ฒŒ ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์ปจํŠธ๋กค๋Ÿฌ๋กœ ์ธ์‹ํ•˜๋„๋ก ์ง€์ •ํ•œ๋‹ค.

@RequestMapping annotation

@RequestMapping ์–ด๋…ธํ…Œ์ด์…˜์€ ํŠน์ • URL์„ ํด๋ž˜์Šค ์ „์ฒด ๋˜๋Š” ํŠน์ • ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ์™€ ๋งคํ•‘ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ์ด ๊ฒฝ์šฐ ํ•ด๋‹น ์–ด๋…ธํ…Œ์ด์…˜์€ home() ๋ฉ”์„œ๋“œ๊ฐ€ URL /์— ๋Œ€ํ•œ GET ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ๊ฒƒ์ž„์„ ์ง€์ •ํ•œ๋‹ค.

@Controller(@Compponet,@Service,@Repository)

@Component, @Service, @Repository๋Š” Spring ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ๋นˆ์„ ์„ ์–ธํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค. ์ด๋“ค์€ ๋ชจ๋‘ @Component ์–ด๋…ธํ…Œ์ด์…˜์˜ ํŠน์ˆ˜ํ•œ ํ˜•ํƒœ์ด๋ฉฐ, ๊ฐ๊ฐ์˜ ๋ชฉ์ ์— ๋”ฐ๋ผ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

@Component: Spring ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ผ๋ฐ˜์ ์ธ ์–ด๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์„ธ๋ถ€ ์–ด๋…ธํ…Œ์ด์…˜๋“ค์˜ ๋ถ€๋ชจ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ํด๋ž˜์Šค๋ฅผ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ  Spring ์ปจํ…Œ์ด๋„ˆ์— ์˜ํ•ด ๊ด€๋ฆฌ๋˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
@Service: ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ํฌํ•จ๋œ ์„œ๋น„์Šค ๊ณ„์ธต์˜ ํด๋ž˜์Šค๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ฃผ๋กœ ์„œ๋น„์Šค ํด๋ž˜์Šค์— ์‚ฌ์šฉ๋˜๋ฉฐ, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๊ณ  ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ ๋“ฑ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
@Repository: ๋ฐ์ดํ„ฐ ์•ก์„ธ์Šค ๋กœ์ง์„ ๋‹ด๋‹นํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ฃผ๋กœ DAO(Data Access Object)๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ๋‹ด๋‹นํ•˜๋Š” ํด๋ž˜์Šค์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ฃผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•˜๊ณ  ์กฐ์ž‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๋ฉฐ, ์˜ˆ์™ธ๋ฅผ ์Šคํ”„๋ง์˜ ์ผ๊ด€๋œ ์˜ˆ์™ธ๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
์ด ์„ธ ๊ฐ€์ง€ ์–ด๋…ธํ…Œ์ด์…˜์€ ๋ชจ๋‘ @Component ์–ด๋…ธํ…Œ์ด์…˜์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ, ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ฝ”๋“œ๋ฅผ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ํ‘œํ˜„ํ•˜๊ณ  ์˜๋ฏธ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ์ปดํฌ๋„ŒํŠธ ์Šค์บ”(Component Scan) ์‹œ์— Spring์ด ์ด๋“ค์„ ์ธ์‹ํ•˜์—ฌ ์ž๋™์œผ๋กœ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด์ค๋‹ˆ๋‹ค.


@Controller(Mapping Requests : Class)

Class : ํด๋ž˜์Šค๋Š” ์ปจํŠธ๋กค๋Ÿฌ์˜ ๊ธฐ๋ณธ ๊ตฌ์„ฑ ์š”์†Œ์ž…๋‹ˆ๋‹ค. @Controller ์• ๋…ธํ…Œ์ด์…˜์ด ์ง€์ •๋œ ํด๋ž˜์Šค๋Š” ์Šคํ”„๋ง MVC์—์„œ ์ปจํŠธ๋กค๋Ÿฌ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ปจํŠธ๋กค๋Ÿฌ ํด๋ž˜์Šค๋Š” ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Controller
@RequestMapping("/appointments")
public class AppointmentsController 
{
    // an HTTP POST for /appointments
    @RequestMapping(method = RequestMethod.POST)
    public Map<String, Appointment> get() {
        return appointmentBook.getAppointmentsForToday();
    }
     
    // an HTTP GET for /appointments/new
    @RequestMapping(value="/new", method = RequestMethod.GET)
    public AppointmentForm getNewForm() {
        return new AppointmentForm();
    }
}

์ƒ์„ธ ์ฝ”๋“œ ์„ค๋ช… : 

๋”๋ณด๊ธฐ

์œ„์˜ ์ฝ”๋“œ๋Š” Spring MVC์—์„œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ •์˜ํ•˜๋Š” ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

1. @Controller: ์ด ์–ด๋…ธํ…Œ์ด์…˜์€ ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ์ปจํŠธ๋กค๋Ÿฌ์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. Spring์ด ์ด ํด๋ž˜์Šค๋ฅผ ์ปดํฌ๋„ŒํŠธ ์Šค์บ”ํ•˜์—ฌ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ , ์š”์ฒญ ๋งคํ•‘์„ ์ฒ˜๋ฆฌํ•  ์ค€๋น„๋ฅผ ํ•ฉ๋‹ˆ๋‹ค.
2. @RequestMapping("/appointments"): ํด๋ž˜์Šค ์ˆ˜์ค€์—์„œ์˜ ์š”์ฒญ ๋งคํ•‘์ž…๋‹ˆ๋‹ค. ์ด ํด๋ž˜์Šค์˜ ๋ชจ๋“  ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์š”์ฒญ URL์˜ ์ ‘๋‘์‚ฌ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์ด ํด๋ž˜์Šค ๋‚ด์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์š”์ฒญ์€ "/appointments"๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
3. @RequestMapping(method = RequestMethod.POST): HTTP POST ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. "/appointments"๋กœ ๋“ค์–ด์˜ค๋Š” POST ์š”์ฒญ์€ ์ด ๋ฉ”์„œ๋“œ์—์„œ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
4. public Map<String, Appointment> get() { ... }: POST ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. appointmentBook์—์„œ ์˜ค๋Š˜์˜ ์˜ˆ์•ฝ์„ ๊ฐ€์ ธ์™€์„œ Map์œผ๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
5. @RequestMapping(value="/new", method = RequestMethod.GET): "/appointments/new" ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜ค๋Š” HTTP GET ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
6. public AppointmentForm getNewForm() { ... }: GET ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ์˜ˆ์•ฝ์„ ์œ„ํ•œ ํผ์„ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ •์˜ํ•˜๋ฉด Spring MVC๋Š” ์š”์ฒญ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ํด๋ผ์ด์–ธํŠธ์— ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

@Controller(Mapping Requests : Handler)

Handler : Class๋ฅผ ์ œ์™ธํ•˜๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ์— ์ฝ”๋“œ์˜ ์–‘์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.
ํ•ธ๋“ค๋Ÿฌ๋Š” ์š”์ฒญ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ ๋กœ์ง์„ ์ •์˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. ์ปจํŠธ๋กค๋Ÿฌ ํด๋ž˜์Šค ๋‚ด๋ถ€์˜ ๊ฐ ๋ฉ”์„œ๋“œ๋Š” ํŠน์ • URL ๊ฒฝ๋กœ์™€ HTTP ์š”์ฒญ ๋ฉ”์„œ๋“œ(์˜ˆ: GET, POST)์™€ ๋งคํ•‘๋˜์–ด ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ํ•ธ๋“ค๋Ÿฌ๋Š” @RequestMapping ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์ • URL ๊ฒฝ๋กœ์™€ ์š”์ฒญ ๋ฉ”์„œ๋“œ์— ๋งคํ•‘๋ฉ๋‹ˆ๋‹ค.

@Controller
public class EmployeeController 
{
    @RequestMapping("/employee-management/employees")
    public String getAllEmployees(Model model)
    {
        //application code
        return "employeesList";
    }
     
    @RequestMapping("/employee-management/employees/add")
    public String addEmployee(EmployeeVO employee)
    {
        //application code
        return "employeesDetail";
    }
}

์ƒ์„ธ ์ฝ”๋“œ ์„ค๋ช… :

๋”๋ณด๊ธฐ

์œ„์˜ ์ฝ”๋“œ๋Š” Spring MVC์—์„œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ์ธ EmployeeController ํด๋ž˜์Šค๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

1. @Controller: ์ด ์–ด๋…ธํ…Œ์ด์…˜์€ ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ์ปจํŠธ๋กค๋Ÿฌ์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. Spring์ด ์ด ํด๋ž˜์Šค๋ฅผ ์ปดํฌ๋„ŒํŠธ ์Šค์บ”ํ•˜์—ฌ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ , ์š”์ฒญ ๋งคํ•‘์„ ์ฒ˜๋ฆฌํ•  ์ค€๋น„๋ฅผ ํ•ฉ๋‹ˆ๋‹ค.
2. @RequestMapping("/employee-management/employees"): "/employee-management/employees" ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ”์„œ๋“œ์ธ getAllEmployees()๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
3. public String getAllEmployees(Model model) { ... }: "/employee-management/employees" ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. Model ๊ฐ์ฒด๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„์™€์„œ, ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ทฐ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•œ ํ›„, "employeesList" ๋ทฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
4. @RequestMapping("/employee-management/employees/add"): "/employee-management/employees/add" ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ”์„œ๋“œ์ธ addEmployee()๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
5. public String addEmployee(EmployeeVO employee) { ... }: "/employee-management/employees/add" ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. EmployeeVO ๊ฐ์ฒด๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„์™€์„œ, ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ ์ง์›์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋“ฑ์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ํ›„, "employeesDetail" ๋ทฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ •์˜ํ•˜๋ฉด Spring MVC๋Š” ์š”์ฒญ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ํด๋ผ์ด์–ธํŠธ์— ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์œ„์˜ ์ฝ”๋“œ์—์„œ ์ฒซ ๋ฒˆ์งธ ํด๋ž˜์Šค AppointmentsController์™€ ๋‘ ๋ฒˆ์งธ ํด๋ž˜์Šค EmployeeController๋Š” ๋ชจ๋‘ ์Šคํ”„๋ง MVC์˜ ์ปจํŠธ๋กค๋Ÿฌ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‘ ํด๋ž˜์Šค ๊ฐ„์—๋Š” ๋ช‡ ๊ฐ€์ง€ ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

URL ๋งคํ•‘:
AppointmentsController(class) : @RequestMapping("/appointments")๋กœ ์ง€์ •๋˜์–ด ์žˆ์–ด, ๋ชจ๋“  ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๋Š” /appointments ๊ฒฝ๋กœ ์•„๋ž˜์—์„œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
EmployeeController(handler) : @RequestMapping("/employee-management/employees")๋กœ ์ง€์ •๋˜์–ด ์žˆ์–ด, ๋ชจ๋“  ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๋Š” /employee-management/employees ๊ฒฝ๋กœ ์•„๋ž˜์—์„œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
HTTP ์š”์ฒญ ๋ฉ”์„œ๋“œ:
AppointmentsController(class) : ์ฒซ ๋ฒˆ์งธ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ(get())๋Š” HTTP POST ๋ฉ”์„œ๋“œ์™€ ๋งคํ•‘๋˜์–ด ์žˆ์œผ๋ฉฐ, ๋‘ ๋ฒˆ์งธ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ(getNewForm())๋Š” HTTP GET ๋ฉ”์„œ๋“œ์™€ ๋งคํ•‘๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
EmployeeController(handler) : ๋‘ ๊ฐœ์˜ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ ๋ชจ๋‘ ๋ช…์‹œ์ ์œผ๋กœ HTTP ์š”์ฒญ ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ, ๊ธฐ๋ณธ์ ์œผ๋กœ GET ์š”์ฒญ์— ๋งคํ•‘๋ฉ๋‹ˆ๋‹ค.
๋ฆฌํ„ด ํƒ€์ž…:
AppointmentsController(class) : ์ฒซ ๋ฒˆ์งธ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ(get())๋Š” Map<String, Appointment>์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ(getNewForm())๋Š” AppointmentForm ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
EmployeeController(handler) : ๋‘ ๊ฐœ์˜ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ ๋ชจ๋‘ String์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ๋ฉ”์„œ๋“œ๋Š” employeesList ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ ๋ฉ”์„œ๋“œ๋Š” employeesDetail ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
์ด๋Ÿฌํ•œ ์ฐจ์ด์ ๋“ค์€ ๊ฐ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ๊ฒฝ๋กœ์™€ ์š”์ฒญ ์œ ํ˜•์— ๋Œ€ํ•œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ฐ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๊ฐ€ ๋‹ค๋ฅธ ์œ ํ˜•์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

@Controller Example(์ถ”๊ฐ€์  ์„ค๋ช…)

Add attributes to the model

Retrieve request parameters as regular parameters


@RequestParam์€ Spring MVC์—์„œ HTTP ์š”์ฒญ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ”์ธ๋”ฉํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค. ์ด ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด HTTP ์š”์ฒญ์˜ ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด์ด๋‚˜ POST ์š”์ฒญ์˜ ํผ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด doLogin() ๋ฉ”์„œ๋“œ๊ฐ€ GET ๋ฐฉ์‹์˜ "/login" ๊ฒฝ๋กœ์— ๋งคํ•‘๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” @RequestParam ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ username๊ณผ password๋ผ๋Š” ๋‘ ๊ฐœ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ์—์„œ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด Spring MVC๋Š” ํ•ด๋‹น ์š”์ฒญ์˜ ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด์—์„œ username๊ณผ password ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ฐพ์•„ ํ•ด๋‹น ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋ฐ”์ธ๋”ฉํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, ์ด ๋ฉ”์„œ๋“œ๋Š” GET ๋ฐฉ์‹์œผ๋กœ "/login" ๊ฒฝ๋กœ์— ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ „๋‹ฌํ•œ username๊ณผ password๋ฅผ ๋ฐ›์•„์™€์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ฒ˜๋ฆฌ ํ›„์—๋Š” ์„ฑ๊ณต ํŽ˜์ด์ง€์˜ ๊ฒฝ๋กœ์ธ success๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.


* View

JSTL & prefix

<?xml version="1.0" encoding="UTF-8" ?>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>

<c:forEach var="i" begin="0" end="5">
	Item <c:out value="${i}"/><p>
</c:forEach>

<c:if test="${fn:length(friends) > 0}" >
	<%@include file="welcome.jsp" %>
</c:if>

JSTL(JavaServer Pages Standard Tag Library)์€ JSP(JavaServer Pages)์—์„œ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ๋ฐ˜๋ณต, ์กฐ๊ฑด ๋“ฑ์˜ ๋กœ์ง์„ ๊ฐ„ํŽธํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ๊ณต๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. JSTL์€ XML ํ˜•์‹์œผ๋กœ ์ •์˜๋˜์–ด ์žˆ์œผ๋ฉฐ, JSP ํŽ˜์ด์ง€์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” <%@taglib %> ๋””๋ ‰ํ‹ฐ๋ธŒ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํƒœ๊ทธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ prefix๋Š” ํƒœ๊ทธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ •์˜๋œ ๊ฐ ํƒœ๊ทธ๋ฅผ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•œ ์ ‘๋‘์‚ฌ(prefix)๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. JSP ํŽ˜์ด์ง€์—์„œ JSTL ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ํ•ด๋‹น ์ ‘๋‘์‚ฌ์™€ ํƒœ๊ทธ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์—ฌ ํƒœ๊ทธ๋ฅผ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, c:forEach๋Š” JSTL Core ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ •์˜๋œ ๋ฐ˜๋ณต ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ํƒœ๊ทธ์ด๋ฉฐ, fn:length๋Š” JSTL Functions ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ •์˜๋œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํƒœ๊ทธ์ž…๋‹ˆ๋‹ค.

์•„๋ž˜๋Š” ์ฃผ์–ด์ง„ ์ฝ”๋“œ์—์„œ ์‚ฌ์šฉ๋œ JSTL ํƒœ๊ทธ๋“ค์˜ ์„ค๋ช…์ž…๋‹ˆ๋‹ค:

1. <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>: ์ด ๋””๋ ‰ํ‹ฐ๋ธŒ๋Š” JSTL Core ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์œผ๋กœ, c ์ ‘๋‘์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ํƒœ๊ทธ๋“ค์„ ์ฐธ์กฐํ•  ๊ฒƒ์ž„์„ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.
2. <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>: ์ด ๋””๋ ‰ํ‹ฐ๋ธŒ๋Š” JSTL Functions ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์œผ๋กœ, fn ์ ‘๋‘์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ํ•จ์ˆ˜๋ฅผ ์ฐธ์กฐํ•  ๊ฒƒ์ž„์„ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.
3. <c:forEach var="i" begin="0" end="5">: ์ด ํƒœ๊ทธ๋Š” JSTL Core ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋ฐ˜๋ณต ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ํƒœ๊ทธ์ž…๋‹ˆ๋‹ค. var ์†์„ฑ์€ ๋ฐ˜๋ณต๋ฌธ ๋‚ด์—์„œ ํ˜„์žฌ ํ•ญ๋ชฉ์„ ์ฐธ์กฐํ•  ๋ณ€์ˆ˜๋ช…์„ ์ง€์ •ํ•˜๊ณ , begin๊ณผ end ์†์„ฑ์€ ๋ฐ˜๋ณต ๋ฒ”์œ„์˜ ์‹œ์ž‘๊ณผ ๋์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
4. <c:if test="${fn:length(friends) > 0}" >: ์ด ํƒœ๊ทธ๋Š” JSTL Core ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์กฐ๊ฑด ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ํƒœ๊ทธ์ž…๋‹ˆ๋‹ค. test ์†์„ฑ์—๋Š” ์กฐ๊ฑด์„ ์ง€์ •ํ•˜๋ฉฐ, ${fn:length(friends) > 0}๋Š” JSTL Functions ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ fn:length() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ friends๋ผ๋Š” ๊ฐ์ฒด์˜ ๊ธธ์ด๊ฐ€ 0๋ณด๋‹ค ํฐ์ง€๋ฅผ ํ™•์ธํ•˜๋Š” ์กฐ๊ฑด์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ JSTL์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ prefix๋ฅผ ์„ค์ •ํ•˜์—ฌ ํ•ด๋‹น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ํƒœ๊ทธ๋“ค์„ ์‰ฝ๊ฒŒ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฐ˜๋ณต, ์กฐ๊ฑด ๋“ฑ์˜ ๋กœ์ง์„ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.





728x90

'๐Ÿ“•JAVA > Spring' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

6week  (0) 2024.04.21
5week  (0) 2024.04.20
4week  (0) 2024.04.04
2week  (0) 2024.03.12
OT - 1week  (0) 2024.03.05
Comments