Bibi's DevLog ๐Ÿค“๐ŸŽ

[Spring] ์ธํ”„๋Ÿฐ ์Šคํ”„๋ง ์ž…๋ฌธ(๊น€์˜ํ•œ ๋‹˜) - ์›น MVC ๊ฐœ๋ฐœ(ํšŒ์›๊ด€๋ฆฌ ์˜ˆ์ œ) : ํšŒ์› ๋“ฑ๋ก ๋ฐ ์กฐํšŒ ๋ณธ๋ฌธ

๐Ÿ–ฅ BE ๋ฐฑ์—”๋“œ/Spring ์Šคํ”„๋ง

[Spring] ์ธํ”„๋Ÿฐ ์Šคํ”„๋ง ์ž…๋ฌธ(๊น€์˜ํ•œ ๋‹˜) - ์›น MVC ๊ฐœ๋ฐœ(ํšŒ์›๊ด€๋ฆฌ ์˜ˆ์ œ) : ํšŒ์› ๋“ฑ๋ก ๋ฐ ์กฐํšŒ

๋น„๋น„ bibi 2021. 3. 5. 00:01

์ด ๊ธ€์€ ์ธํ”„๋Ÿฐ ๊น€์˜ํ•œ ๋‹˜์˜ ์Šคํ”„๋ง ์ž…๋ฌธ ๊ฐ•์˜ ๋ฅผ ๋“ฃ๊ณ  ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

ํšŒ์› ๊ด€๋ฆฌ ์˜ˆ์ œ - ์›น MVC ๊ฐœ๋ฐœ

ํšŒ์› ์›น ๊ธฐ๋Šฅ - ํ™ˆ ํ™”๋ฉด ์ถ”๊ฐ€

์•„์ฃผ ๋‹จ์ˆœํ•œ 1.ํšŒ์› ๋“ฑ๋ก ๋ฐ 2.ํšŒ์› ์กฐํšŒ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ํ™”๋ฉด์„ ๋งŒ๋“ค์–ด ๋ณธ๋‹ค.

  • @GetMapping("/") : URL์—์„œ /๋Š” ๋„๋ฉ”์ธ์œผ๋กœ ์ฒ˜์Œ ๋“ค์–ด์™”์„ ๋•Œ์˜ ํŽ˜์ด์ง€๋ฅผ ๋งํ•จ. (ํ™ˆ ํŽ˜์ด์ง€)

    • index.html๊ณผ์˜ ์ฐจ์ด๋Š”?? (src/main/java/resources/static/index.html)

      (๋ณต์Šต) ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด, ํ†ฐ์บฃ ์„œ๋ฒ„๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ ๊ด€๋ จ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋จผ์ € ์ฐพ๊ณ , ๊ด€๋ จ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์—†์œผ๋ฉด ๊ทธ ๋•Œ staticํด๋”๋ฅผ ์ฐพ๋Š”๋‹ค. ๊ทธ๋ž˜์„œ static์— ์žˆ๋Š” index.html๋ณด๋‹ค @GetMapping("/")์ด ๋จผ์ € ์ฐพ์•„์ง„๋‹ค.

  • @GetMapping() ๋ฉ”์†Œ๋“œ์˜ ๋ฆฌํ„ด๊ฐ’์€ src/main/java/resources/templates์—์„œ ์ฐพ๋Š”๋‹ค.

src/main/java/ํ”„๋กœ์ ํŠธ๋ช…/controller/HomeController.java

package hello.hellospring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {

    @GetMapping("/")
    public String home() {
        return "home";
    }
}

src/main/java/resource/templates/home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="container">
    <div>
        <h1>Hello Spring</h1>
        <p>ํšŒ์› ๊ธฐ๋Šฅ</p>
        <p>
            <a href="/members/new">ํšŒ์› ๊ฐ€์ž…</a>
            <a href="/members">ํšŒ์› ๋ชฉ๋ก</a>
        </p>
    </div>
</div>
</body>
</html>

ํšŒ์› ์›น ๊ธฐ๋Šฅ - ๋“ฑ๋ก

์ด์ „์— ๋งŒ๋“ค์–ด ๋‘” MemberController๋ฅผ ํ™œ์šฉํ•ด ๋งŒ๋“ ๋‹ค.

home.html์— ์—ฐ๊ฒฐํ•ด ๋‘” ํšŒ์›๊ฐ€์ž… url์ธ /members/new ํ™”๋ฉด์„ ๋งŒ๋“ค๊ณ  ๋™์ž‘ํ•˜๊ฒŒ ํ•œ๋‹ค.

MemberController.java

์•„๋ž˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

@GetMapping("/members/new")
    public String createForm() {
        return "members/createMemberForm";
}
  • members/createMemberForm์ด๋Ÿฐ url์€ src/main/java/resources/templates์—์„œ๋ถ€ํ„ฐ์˜ ๊ฒฝ๋กœ๋กœ ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.
    • ์ฆ‰ templates๋””๋ ‰ํ† ๋ฆฌ์— members๋ผ๋Š” ํ•˜์œ„ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ , ๊ทธ ํ•˜์œ„ ๋””๋ ‰ํ† ๋ฆฌ ์•ˆ์— createMemberForm.html์„ ๋งŒ๋“ค๋ฉด ๋ฆฌํ„ด์‹œ ํ•ด๋‹น htmlํŒŒ์ผ๋กœ ์—ฐ๊ฒฐ๋œ๋‹ค.

createMemberForm.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="container">
    <form action="/members/new" method="post">
        <div class="form-group">
            <label for="name">์ด๋ฆ„</label>
            <input type="text" id="name" name="name" placeholder="์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”">
        </div>
        <button type="submit">๋“ฑ๋ก</button>
    </form>
</div>
</body>
</html>
  • <form action="/members/new" method="post">

    • <form>์€ ๊ฐ’์„ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” htmlํƒœ๊ทธ

    • action="/members/new" method="post"

    • <input type="text" id="name" name="name" placeholder="์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”">

      ์—ฌ๊ธฐ์—์„œ name="name"์ด ์„œ๋ฒ„์— ๋„˜์–ด์˜ฌ ๋•Œ์˜ ํ‚คkey๊ฐ€ ๋œ๋‹ค.

  • ๋“ฑ๋ก ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด action="/members/new" method="post"์— ๋”ฐ๋ผ,

    • /members/new URL๋กœ POST๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ๋„˜์–ด๊ฐ„๋‹ค.
    • ๋ฐ์ดํ„ฐ๋Š” @PostMapping("/members/new")๋กœ ๋„˜์–ด๊ฐ„๋‹ค. (์•„๋ž˜ ์ฐธ๊ณ )

ํšŒ์›์„ ๋“ฑ๋กํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ MemberForm.java๋ฅผ src/main/java/ํ”„๋กœ์ ํŠธ๋ช…/controller์— ๋งŒ๋“ ๋‹ค

MemberForm.java

package hello.hellospring.controller;

public class MemberForm {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

MemberController.java

์•„๋ž˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค

@PostMapping("/members/new")
public String create(MemberForm form) {
    Member member = new Member();
    member.setName(form.getName());

    memberService.join(member);

    return "redirect:/";
}
  • return "redirect:/"; : ํ•ด๋‹น ๋ฉ”์„œ๋“œ๊ฐ€ ๋๋‚˜๋ฉด redirect:์ดํ•˜๋กœ ์—ฐ๊ฒฐํ•ด ์คŒ. ์—ฌ๊ธฐ์„œ๋Š” /์ด๋ฏ€๋กœ ํ™ˆ ํ™”๋ฉด์œผ๋กœ ๋Œ์•„๊ฐ.

  • @PostMapping() (POST๋ฐฉ์‹) : ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ(๋“ฑ๋ก)ํ•  ๋•Œ ์‚ฌ์šฉํ•จ.

  • @GetMapping() (GET ๋ฐฉ์‹) : ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ ์‚ฌ์šฉํ•จ. URL์— ์ง์ ‘ ์ž…๋ ฅ์„ ํ†ตํ•ด ๋™์ž‘.

    ์ฆ‰ URL์€ ๊ฐ™์ง€๋งŒ GET / POST ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ๋งตํ•‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

    • ViewResolver(๋ทฐ ๋ฆฌ์กธ๋ฒ„)๊ฐ€ ๋ฆฌํ„ด ๊ฐ’์„ templates์—์„œ ์ฐพ์•„ ํ•ด๋‹น htmlํŒŒ์ผ์„ ์„ ํƒํ•˜๊ณ , Thymeleaf ํ…œํ”Œ๋ฆฟ์—”์ง„์ด ํŒŒ์ผ์„ ๋ Œ๋”๋งํ•œ๋‹ค. ์ฆ‰ ํ™”๋ฉด์— html์ด ๋ฟŒ๋ ค์ง„๋‹ค.
  • action="/members/new" method="post"์— ๋”ฐ๋ผ ๋„˜์–ด์˜จ ๋ฐ์ดํ„ฐ name="name" ์€ ,

    create(MemberForm form)์—์„œ MemberForm๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ์˜ ์ธ์Šคํ„ด์Šค๋ณ€์ˆ˜ private String name;์œผ๋กœ ์ง€์ •๋œ๋‹ค (์Šคํ”„๋ง์ด setName(String name)์„ ํ†ตํ•ด name="name"์„ ๋งตํ•‘ํ•ด์ค€๋‹ค)

HTML GET / POST ๋ฐฉ์‹ ๋ฐ <form>ํƒœ๊ทธ์— ๋Œ€ํ•ด ๋” ๊ฒ€์ƒ‰ ๋ฐ ๊ณต๋ถ€ํ•ด๋ณด๋ฉด ์ดํ•ด๊ฐ€ ๋  ๊ฒƒ์ด๋‹ค.

ํšŒ์› ์›น ๊ธฐ๋Šฅ - ์กฐํšŒ

์ด์ œ ํšŒ์› ๋ชฉ๋ก์„ ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ๋งŒ ๊ตฌํ˜„ํ•˜๋ฉด ๋œ๋‹ค.

MemberController.java

์•„๋ž˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

@GetMapping("/members")
public String list(Model model) {
    List<Member> members = memberService.findMembers();
    model.addAttribute("members", members); // ํ‚ค "members", ๊ฐ’ members๋กœ Model์— ์ €์žฅ
    return "members/memberList";
}

memberList.html (src/main/java/resources/templates์— ์ƒ์„ฑ)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="container">
    <div>
        <table>
            <thead>
            <tr>
                <th>#</th>
                <th>์ด๋ฆ„</th>
            </tr>
            </thead>
            <tbody>
            <tr th:each="member : ${members}">
                <td th:text="${member.id}"></td>
                <td th:text="${member.name}"></td>
            </tr>
            </tbody>
        </table>
    </div>
</div>
</body>
</html>

th : thymeleaf ํ…œํ”Œ๋ฆฟ์—”์ง„์„ ์‚ฌ์šฉํ•˜๋Š” ๋ถ€๋ถ„.

ํ…œํ”Œ๋ฆฟ์—”์ง„์˜ ์—ญํ• ์€ ๋ Œ๋”๋ง์ด๋‹ค.

<tr th:each="member : ${members}">
    <td th:text="${member.id}"></td>
    <td th:text="${member.name}"></td>
</tr>
  • th:each="member : ${members}"์—์„œ..

    • th:each๋Š” Thymeleaf์˜ ๋ฐ˜๋ณต๋ฌธ ๋ฌธ๋ฒ•์ด๋‹ค. ๋ฃจํ”„๋ฅผ ๋Œ๋ฉฐ ํ•ด๋‹น ํƒœ๊ทธ ๋‚ด์˜ ํƒœ๊ทธ๋“ค์„ ์‹คํ–‰ํ•œ๋‹ค.

    • member๋Š” ๋ฐ˜๋ณต๋˜๋Š” ๊ฐ์ฒด ํ•˜๋‚˜์— ๋Œ€ํ•œ ์ž„์‹œ๋ณ€์ˆ˜๋ช…์ด๋‹ค.

    • ${members}๋Š” Model์—์„œ members๋ผ๋Š” ํ‚ค๋ฅผ ๊ฐ€์ง€๋Š” ๊ฐ’์„ ์ฐพ์•„ ๊ฐ€์ง€๊ณ  ์˜จ๋‹ค.

      MemberController.java์—์„œ model.addAttribute("members", members);๋กœ members(List)๋ฅผ ์ €์žฅํ•ด ๋†“์•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ.

  • th:text="${member.id}", th:text="${member.name}"

    • th:each์˜ ์ž„์‹œ๋ณ€์ˆ˜ member์˜ id์™€ name์„ ๊ฐ๊ฐ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.

    • id์™€ name์€ private์ธ๋ฐ ์–ด๋–ป๊ฒŒ ๊ฐ€์ ธ์™”๋Š”๊ฐ€?

      : Memberํด๋ž˜์Šค์— ์ •์˜๋œ getter, setter์— ์ ‘๊ทผํ•ด ๊ฐ’์„ ๊ฐ€์ ธ์˜จ ๊ฒƒ์ด๋‹ค. (์ด๋ฅผ 'ํ”„๋กœํผํ‹ฐ๋ฐฉ์‹์˜ ์ ‘๊ทผ'์ด๋ผ๊ณ  ํ•œ๋‹ค)

์—ฌ๊ธฐ๊นŒ์ง€ ์ž˜ ๋˜์—ˆ์ง€๋งŒ, ํ˜„์žฌ ๋ฐ์ดํ„ฐ๋“ค์€ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์Šคํ”„๋ง ์„œ๋ฒ„๋ฅผ ๋„๋ฉด ํšŒ์› ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ค ์‚ฌ๋ผ์ง„๋‹ค.

์ด์ œ ํŒŒ์ผ์ด๋‚˜ DB์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ด์•ผ ํ•œ๋‹ค.

๋‹ค์Œ ์‹œ๊ฐ„์— ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ ์—‘์„ธ์Šค (๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‚ฌ์šฉ)์— ๋Œ€ํ•ด ๋ฐฐ์›Œ ๋ณผ ๊ฒƒ์ด๋‹ค.

'๐Ÿ–ฅ BE ๋ฐฑ์—”๋“œ > Spring ์Šคํ”„๋ง' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Spring] ์ธํ”„๋Ÿฐ ์Šคํ”„๋ง ์ž…๋ฌธ(๊น€์˜ํ•œ ๋‹˜) - ์ˆœ์ˆ˜JDBC, ํ†ตํ•ฉํ…Œ์ŠคํŠธ, ์Šคํ”„๋งJdbcTemplate, JPA, ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA  (0) 2021.03.06
[Spring] ์ธํ”„๋Ÿฐ ์Šคํ”„๋ง ์ž…๋ฌธ(๊น€์˜ํ•œ ๋‹˜) - ์Šคํ”„๋ง DB ์ ‘๊ทผ๊ธฐ์ˆ  : H2 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค์น˜  (0) 2021.03.05
[Spring] ์ธํ”„๋Ÿฐ ์Šคํ”„๋ง ์ž…๋ฌธ(๊น€์˜ํ•œ ๋‹˜) - ์Šคํ”„๋ง ๋นˆ๊ณผ ์˜์กด๊ด€๊ณ„ : ์ปดํฌ๋„ŒํŠธ ์Šค์บ”, ์˜์กด๊ด€๊ณ„, DI, ์Šคํ”„๋ง ๋นˆ ์ง์ ‘ ๋“ฑ๋กํ•˜๊ธฐ  (0) 2021.03.04
[Spring] ์ธํ”„๋Ÿฐ ์Šคํ”„๋ง ์ž…๋ฌธ(๊น€์˜ํ•œ ๋‹˜) - ํšŒ์› ๊ด€๋ฆฌ ์˜ˆ์ œ:๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ, ํšŒ์› ๋„๋ฉ”์ธ/๋ฆฌํฌ์ง€ํ† ๋ฆฌ/์„œ๋น„์Šค ๊ฐœ๋ฐœ, ํ…Œ์ŠคํŠธ์ผ€์ด์Šค ์ž‘์„ฑ  (0) 2021.03.04
[Spring] ์ธํ”„๋Ÿฐ ์Šคํ”„๋ง ์ž…๋ฌธ(๊น€์˜ํ•œ ๋‹˜) - ๋นŒ๋“œ ๋ฐ ์‹คํ–‰, ์ •์  ์ปจํ…์ธ /MVC์™€ ํ…œํ”Œ๋ฆฟ์—”์ง„/API  (0) 2021.03.04