๐Ÿ”ฎ GitHub ๋ฐ”๋กœ๊ฐ€๊ธฐ

1 Spring MVC - Response

๐Ÿ“Œ Spring MVC : MVC (Model - View - Controller) ์†Œํ”„ํŠธ์›จ์–ด ๋””์ž์ธํŒจํ„ด

Layer์—ญํ• 
Model์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ •๋ณด ๋ฐ ๋ฐ์ดํ„ฐ
Viewํ…์ŠคํŠธ, ์ฒดํฌ๋ฐ•์Šค ๋“ฑ ์‚ฌ์šฉ์ž์ธํ„ฐํŽ˜์ด์Šค ์š”์†Œ
Controller๋ฐ์ดํ„ฐ์™€ ๋น„์ฆˆ๋‹ˆ์Šค๋กœ์ง ์‚ฌ์ด์˜ ์ƒํ˜ธ๋™์ž‘ ๊ด€๋ฆฌ
  • Client Request ํ•˜๋ฉด,

  • Server์—์„œ HTML์„ ๋‚ด๋ ค์ค„ ๋•Œ โžก๏ธ static or dynamic์œผ๋กœ ๋‚ด๋ ค์คŒ

1๏ธโƒฃ static ์ •์ ์›นํŽ˜์ด์ง€

  • Controller

    • Client Request โ†’ Model๋กœ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•จ
      (ex. ํšŒ์›๊ฐ€์ž…์„ ์œ„ํ•œ ID, PW, NAME โ€ข โ€ข โ€ข)

    • Client์—๊ฒŒ View ๋‚ด๋ ค์คŒ
      (์ •์ ์›นํŽ˜์ด์ง€, HTML)

2๏ธโƒฃ dynamic ๋™์ ์›นํŽ˜์ด์ง€

  • Controller

    • Client Request โ†’ Model๋กœ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•จ

    • Templete engine์— View, Model ์ „๋‹ฌ

    • Client์—๊ฒŒ View ๋‚ด๋ ค์คŒ
      (๋™์ ์›นํŽ˜์ด์ง€, HTML)

  • Templete engine

    • View์— Model์„ ์ ์šฉํ•จ โ†’ ๋™์ ์ธ ์›นํŽ˜์ด์ง€ ์ƒ์„ฑ
      (ex. ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ, ๋กœ๊ทธ์ธ๋œ์‚ฌ์šฉ์žId โ†’ ํŽ˜์ด์ง€์— ์ถ”๊ฐ€)

    • Thymeleaf ์‚ฌ์šฉ (ํƒ€์ž„๋ฆฌํ”„)


2 MVCํŒจํ„ดproject_HelloMVC

1๏ธโƒฃ ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ


2๏ธโƒฃ ์ •์ ์›นํŽ˜์ด์ง€ ์„ค๊ณ„

๐Ÿ“ resources > static > hello.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Hello Mallang</title>
</head>
<body>
<div>
    Hello, Mallang ์ •์ ์›นํŽ˜์ด์ง€!!
</div>
</body>
</html>

3๏ธโƒฃ ๋™์ ์›นํŽ˜์ด์ง€ ์„ค๊ณ„

๐Ÿ“ templates > hello.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Hello Mallang</title>
</head>
<body>
<div>
  Hello, Mallang templates ํŽ˜์ด์ง€!!
</div>
</body>
</html>

๐Ÿ“ templates > hello-visit.html

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Hello Mallang</title>
</head>
<body>
<div>
  Hello, Mallang ๋™์ ์›นํŽ˜์ด์ง€!!
</div>
<div>
  (๋ฐฉ๋ฌธ์ž ์ˆ˜ : <span th:text = "${visits}"></span>)
</div>
</body>
</html>

๐Ÿ“ controller > HelloResponseController.java

@Controller
@RequestMapping("/response") // ์ „์ฒด url ->  /response๋กœ ์‹œ์ž‘
public class HelloResponseController {
    // ๋ฐฉ๋ฌธ์ž์ˆ˜ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ํด๋ž˜์Šค ๋ณ€์ˆ˜
    private static long visitCount = 0;

    // ์ •์ ์›นํŽ˜์ด์ง€
    @GetMapping("/html/redirect")
    public String htmlFile() {
        return "redirect:/hello.html";
    }

    // ๋™์ ์›นํŽ˜์ด์ง€
    @GetMapping("/html/templates")
    public String htmlTemplates() {
        return "hello";
    }

    // ์ •์ ์›นํŽ˜์ด์ง€
    // ๋ฉ”์„œ๋“œ Return ๊ฐ’ -> View ์ถœ๋ ฅ X
    // HTTP Response Body์— ์“ฐ์—ฌ์ง
    // json ๋ฐ˜ํ™˜
    @ResponseBody
    @GetMapping("/body/html")
    public String helloStringHTML() {
        // return๊ฐ’์ด html -> ๋ฐ”๋กœ ์ ์šฉ๋˜์–ด ๋‚˜์˜ด
        return "<!DOCTYPE html>" +
                "<html>" +
                "<head><meta charset=\"UTF-8\"><title>By @ResponseBody</title></head>" +
                "<body> Hello, Mallang ์ •์  ์›น ํŽ˜์ด์ง€!!</body>" +
                "</html>";
    }

    // ๋™์ ์›นํŽ˜์ด์ง€
    // Thymeleaf๋ฐฉ์‹
    // Model <- Client๊ฐ€ ์›ํ•˜๋Š” ๊ฐ’, hello-visit.html์„ ๋ฐ˜ํ™˜
    @GetMapping("/html/dynamic")
    public String helloHtmlFile(Model model) {
        visitCount++;
        // hello-visit์— visits๋ถ€๋ถ„์— visitCount ์‚ฝ์ž…
        model.addAttribute("visits", visitCount);
        // Controller๋Š” Model์„ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ด, View์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊น€
        return "hello-visit";
    }

    // ๋ฉ”์„œ๋“œ Return ๊ฐ’ -> View ์ถœ๋ ฅ X
    // HTTP Response Body์— ์“ฐ์—ฌ์ง
    // json ๋ฐ˜ํ™˜
    @ResponseBody
    @GetMapping("/json/string")
    public String helloStringJson() {
        // ์ฝ˜์†” <body></body>์— jsonํ˜•ํƒœ๋กœ ์ฐํž˜
        return "{\"name\":\"๋ง๋ž‘\",\"age\":20}";
    }

    @ResponseBody
    @GetMapping("/json/class")
    public Star helloJson() {
        // star ๊ฐ์ฒด๊ฐ€ json ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜๋จ
        return new Star("๋ง๋ž‘", 22);
    }
}

๐Ÿ“ entity > Star.java

@Getter
@Setter
// class ๋ชจ๋“  ํ•„๋“œ๊ฐ’์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š” ์ƒ์„ฑ์ž์ถ”๊ฐ€
@AllArgsConstructor
public class Star {
    public String name;

    public int age;
}

4๏ธโƒฃ Controller์™€ HTTP Response ๋ฉ”์‹œ์ง€

5๏ธโƒฃ @RestController

๐Ÿ“Œ @RestController : @Controller + @ResponseBody
โ†’ View ๋Œ€์‹ , JSON ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜

๐Ÿ“ Controller > HelloRestController.java

// @Controller + @ResponseBody -> Json ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜
@RestController
@RequestMapping("/rest")
public class HelloRestController {
    @GetMapping("/json/string") // ์•„๋ž˜ HTML ๋ฐ˜ํ™˜
    public String helloHtmlString() {
        return "<html><body>Hello @ResponseBody</body></html>";
    }

    @GetMapping("/json/list") // ๋ฆฌ์ŠคํŠธ ๋ฐ˜ํ™˜
    public List<String> helloJson() {
        List<String> words = Arrays.asList("Hello", "Controller", "And", "JSON");

        return words;
    }
}

3 Spring MVC ๋™์ž‘์›๋ฆฌ

๋‹จ๊ณ„๋™์ž‘
1. Client โ†’ DispatcherServlet- โ‘  Client์˜ ์š”์ฒญ์„ ๋ฐ›์Œ
- โ‘ก ๊ฐ€์žฅ ์•ž๋‹จ์—์„œ ์š”์ฒญ์„ ๋ฐ›์Œ โ†’ FrontController ๋ผ๊ณ ๋„ ์‚ฌ์šฉํ•จ
2. DispatcherServlet โ†’ Controller- โ‘  API๋ฅผ ์ฒ˜๋ฆฌํ•  Controller๋ฅผ ์ฐพ์•„ ์š”์ฒญ์„ ์ „๋‹ฌํ•จ
- โ‘ก Handler mapping : API path + Controller ํ•จ์ˆ˜๊ฐ€ ๋งค์นญ๋˜์–ด์žˆ์Œ
(โ†’ Handler mapping์—์„œ ์•Œ๋งž์€ Controller ๋งค์นญ์‹œ์ผœ์ฃผ๋Š” ์—ญํ• )
3. Controller โ†’ DispatcherServlet- โ‘  Controller๊ฐ€ Client๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ API Request ์ฒ˜๋ฆฌ
- โ‘ก Model(View์— ์ ์šฉํ•  ์ •๋ณด๋“ค) + View โ†’ DispatcherServlet์— ์ „๋‹ฌ
4. DispatcherServlet โ†’ Client- โ‘  ViewResolver โ†’ View์— Model ์ ์šฉ
- โ‘ก View โ†’ Client์—๊ฒŒ Response ์ „๋‹ฌ

4 Spring MVC - Request

1๏ธโƒฃ RequestController ์„ค๊ณ„

๐Ÿ“ Controller > HelloRequestController

@Controller
@RequestMapping("/request") // request path๋กœ ์‹œ์ž‘
public class HelloRequestController {
    // hello-request-form htmlํŒŒ์ผ ํ˜ธ์ถœ
    @GetMapping("/form/html")
    public String helloForm() {
        return "hello-request-form";
    }

    @GetMapping("/star/{name}/age/{age}")
    // View๊ฐ€ ์•„๋‹ˆ๋ผ, Jsonํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋งŒ ๋ฐ˜ํ™˜
    // @Controller ์‚ฌ์šฉํ–ˆ๊ธฐ๋•Œ๋ฌธ์— ๋ฉ”์„œ๋“œ๋งˆ๋‹ค ๋ถ™์—ฌ์ค˜์•ผํ•จ
    @ResponseBody
    public String helloRequestPath(@PathVariable String name, @PathVariable int age) {
        // @PathVariable : URL๋กœ ์ „๋‹ฌ๋œ ๊ฐ’ -> ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์•„์˜ด
        return String.format("Hello, @PathVariable. <br> name = %s, age = %d", name, age);
    }

    // param?name=mallang&age=22 (์ฟผ๋ฆฌ์ŠคํŠธ๋ง)
    @GetMapping("/form/param")
    @ResponseBody
    public String helloGetRequestParam(@RequestParam String name, @RequestParam int age) {
        // @RequestParam : URL๋กœ ์ „๋‹ฌ๋œ ๊ฐ’ -> ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์•„์˜ด
        // Get๋ฐฉ์‹์€ URL์— ๊ฐ’์ด ํ‘œ์ถœ๋จ
        return String.format("Hello, @RequestParam. <br> name = %s, age = %d", name, age);
    }

    @PostMapping("/form/param")
    @ResponseBody
    public String helloPostRequestParam(@RequestParam String name, @RequestParam int age) {
        // Post๋ฐฉ์‹์€ URL์— ๊ฐ’์ด ํ‘œ์ถœ๋˜์ง€ ์•Š์Œ
        // ํŽ˜์ด๋กœ๋“œ์— ๊ฐ’์ด ๋“ค์–ด์žˆ์Œ
        return String.format("Hello, @RequestParam. <br> name = %s, age = %d", name, age);
    }

    @PostMapping("/form/model")
    @ResponseBody
    public String helloRequestBodyForm(@ModelAttribute Star star) {
        // @ModelAttribute : ํ•œ๋ฒˆ์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด์— ์ „๋ถ€ ๋‹ด์•„ ๊ฐ€์ ธ์˜ด
        return String.format("Hello, @RequestBody. <br> (name = %s, age = %d)", star.name, star.age);
    }

    @PostMapping("/form/json")
    @ResponseBody
    public String helloPostRequestJson(@RequestBody Star star) {
        // ๊ฐ’์ด HTTP Body์— Jsonํ˜•ํƒœ๋กœ ๋„˜์–ด๊ฐ
        // @RequestBody + ๊ฐ’์„ ๋ฐ›์•„์˜ฌ ๊ฐ์ฒด
        return String.format("Hello, @RequestBody. <br> (name = %s, age = %d)", star.name, star.age);
    }
}

2๏ธโƒฃ RequestForm ์„ค๊ณ„

๐Ÿ“ templates > hello-request-form.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <title>Hello Request</title>
</head>
<body>
<h2>GET /request/star/{name}/age/{age}</h2>
<form id="helloPathForm">
    <div>
        ์ด๋ฆ„: <input name="name" type="text">
    </div>
    <div>
        ๋‚˜์ด: <input name="age" type="text">
    </div>
</form>
<div>
    <button id="helloPathFormSend">์ „์†ก</button>
</div>
<br>

<h2>GET /request/form/param</h2>
<form method="GET" action="/request/form/param">
    <div>
        ์ด๋ฆ„: <input name="name" type="text">
    </div>
    <div>
        ๋‚˜์ด: <input name="age" type="text">
    </div>
    <button>์ „์†ก</button>
</form>

<br>

<h2>POST /request/form/param</h2>
<form method="POST" action="/request/form/param">
    <div>
        ์ด๋ฆ„: <input name="name" type="text">
    </div>
    <div>
        ๋‚˜์ด: <input name="age" type="text">
    </div>
    <button>์ „์†ก</button>
</form>
<br>

<h2>POST /request/form/model</h2>
<form method="POST" action="/request/form/model">
    <div>
        ์ด๋ฆ„: <input name="name" type="text">
    </div>
    <div>
        ๋‚˜์ด: <input name="age" type="text">
    </div>
    <button>์ „์†ก</button>
</form>
<br>

<h2>POST /request/form/json</h2>
<form id="helloJsonForm">
    <div>
        ์ด๋ฆ„: <input name="name" type="text">
    </div>
    <div>
        ๋‚˜์ด: <input name="age" type="text">
    </div>
</form>
<div>
    <button id="helloJsonSend">์ „์†ก</button>
</div>
<div>
    <div id="helloJsonResult"></div>
</div>
</body>
<script>
    // GET /star/{name}/age/{age}
    const helloPathForm = document.querySelector("#helloPathFormSend")
    helloPathForm.onclick = (e) => {
        const form = document.querySelector("#helloPathForm");
        const name = form.querySelector('input[name="name"]').value;
        const age = form.querySelector('input[name="age"]').value;
        const relativeUrl = `/request/star/${name}/age/${age}`;
        window.location.href = relativeUrl;
    }

    // POST /hello/request/form/json
    const helloJson = document.querySelector("#helloJsonSend")
    helloJson.onclick = async (e) => {
        const form = document.querySelector("#helloJsonForm");

        const data = {
            name: form.querySelector('input[name="name"]').value,
            age: form.querySelector('input[name="age"]').value
        }

        const response = await fetch('/request/form/json', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(data),
        })

        const text = await response.text(); // read response body as text
        document.querySelector("#helloJsonResult").innerHTML = text;
    };
</script>
</html>
profile
๐ŸฑSunyeon-Jeong, mallang developer๐Ÿฐ

0๊ฐœ์˜ ๋Œ“๊ธ€