๐Ÿ–‹๏ธ study/spring

[Spring Intro] Section 05. ํšŒ์›๊ด€๋ฆฌ ์˜ˆ์ œ - ์›น MVC ๊ฐœ๋ฐœ(ํšŒ์› ์›น ๊ธฐ๋Šฅ, ํ™ˆ ํ™”๋ฉด ์ถ”๊ฐ€, ๋“ฑ๋ก, ์กฐํšŒ)

๊ธฐ๋ฎจ์ง€ 2023. 1. 25. 02:44

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

# HomeController

java/hello/hellospring/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";
    }
}

> @GetMapping("/")์—์„œ "/"๋Š” ๊ฐ€์žฅ ์ฒ˜์Œ์˜ ๋„๋ฉ”์ธ(localhost:8080)์„ ์˜๋ฏธํ•œ๋‹ค.

> home() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด home.html์ด ํ˜ธ์ถœ๋œ๋‹ค.

 

# Home

resources/templates/home.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
    <div>
        <h1>Hello Spring</h1> <p>ํšŒ์› ๊ธฐ๋Šฅ</p>
        <p>
            <a href="/members/new">ํšŒ์› ๊ฐ€์ž…</a> <a href="/members">ํšŒ์› ๋ชฉ๋ก</a>
        </p>
    </div>
</div> <!-- /container -->
</body>
</html>

 

# ์‹คํ–‰

 

# ์™œ static์˜ index.html ํ™”๋ฉด์ด ๋œจ์ง€ ์•Š๋‚˜์š”?

 

 

์ง€๋‚œ ํฌ์ŠคํŒ… ์ฐธ๊ณ 
Section 02. ์Šคํ”„๋ง ์›น ๊ฐœ๋ฐœ ๊ธฐ์ดˆ - ์ •์  ์ปจํ…์ธ , MVC์™€ ํ…œํ”Œ๋ฆฟ ์—”์ง„, API

 

๋‚ด์žฅ ํ†ฐ์บฃ ์„œ๋ฒ„์—์„œ๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ ๊ด€๋ จ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์žˆ๋Š”์ง€ ๋จผ์ € ์ฐพ๊ณ , ์—†๋‹ค๋ฉด static ํŒŒ์ผ์„ ์ฐพ๋„๋ก ํ–ˆ๋‹ค.

ํ˜„์žฌ HomeController์—์„œ ๋งคํ•‘๋œ home ํ™”๋ฉด์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ํ™”๋ฉด์„ ํ˜ธ์ถœํ•˜๊ณ  ๋๋‚˜๋Š” ๊ฒƒ์ด๋‹ค.

 

์ฆ‰, ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์ •์  ํŒŒ์ผ๋ณด๋‹ค ์šฐ์„  ์ˆœ์œ„๊ฐ€ ๋†’๊ธฐ ๋•Œ๋ฌธ์— home.html ํ™”๋ฉด์ด ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ

 


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

 

ํšŒ์› ๋“ฑ๋ก ํผ ๊ฐœ๋ฐœ

 

# ํšŒ์› ๋“ฑ๋ก ํผ ์ปจํŠธ๋กค๋Ÿฌ

java/hello/hellospring/controller/MemberController.java

@Controller
    public class MemberController {
        private final MemberService memberService;
        
        @Autowired
        public MemberController(MemberService memberService) {
            this.memberService = memberService;
        }
        
        @GetMapping(value = "/members/new")
        public String createForm() {
            return "members/createMemberForm";
        }
}

 

# ํšŒ์› ๋“ฑ๋ก ํผ HTML

resources/templates/members/createMemberForm.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<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> <!-- /container -->
</body>
</html>

 

 

ํšŒ์› ๋“ฑ๋ก ์ปจํŠธ๋กค๋Ÿฌ

# ์›น ๋“ฑ๋ก ํ™”๋ฉด์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ ๋ฐ›์„ ํผ ๊ฐ์ฒด

java/hello/hellospring/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;
    }
}

 

# ํšŒ์› ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ํšŒ์›์„ ์‹ค์ œ ๋“ฑ๋กํ•˜๋Š” ๊ธฐ๋Šฅ

java/hello/hellospring/controller/MemberController.java์— ์•„๋ž˜ ์ฝ”๋“œ ์ถ”๊ฐ€

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

    memberService.join(member);

    return "redirect:/";
}

 

 

# ์‹คํ–‰

์ด์ „ ํ™”๋ฉด์—์„œ ํšŒ์›๊ฐ€์ž…์„ ๋ˆ„๋ฅด๋ฉด ์œ„ ํ™”๋ฉด(/members/new)์œผ๋กœ ์ด๋™ํ•œ๋‹ค.

์ด๋ฆ„์— spring ์ž…๋ ฅ ํ›„ ๋“ฑ๋ก์„ ๋ˆŒ๋ €์„ ๋•Œ ๋‹ค์‹œ ์ด์ „ ํ™”๋ฉด์œผ๋กœ ๋Œ์•„์˜ค๋ฉด ์„ฑ๊ณต์ด๋‹ค.

 

 

ํšŒ์› ๋“ฑ๋ก ์›๋ฆฌ

์œ„ ํ™”๋ฉด(http://localhost:8080/members/new) ์ ‘์†, GET ๋ฐฉ์‹

 

GET ๋ฐฉ์‹์„ ์‚ฌ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— memberController - createForm ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ

return์— ์˜ํ•ด templates > members > createMemberForm์œผ๋กœ ์ด๋™

 

viewResolver์— ์˜ํ•ด createMemberForm์ด ์„ ํƒ๋˜์–ด thymeleaf ํ…œํ”Œ๋ฆฟ ์—”์ง„์ด ๋ Œ๋”๋งํ•˜๋ฉฐ html์ด ํ™”๋ฉด์— ๋ฟŒ๋ ค์ง

 

์ด๋•Œ ๊ฐ’์„ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” form ํƒœ๊ทธ ๋‚ด์˜ input ํƒœ๊ทธ๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด, name="name" ๋ถ€๋ถ„์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ € name์— ๋‚ด๊ฐ€ ์ž…๋ ฅํ•œ ์ด๋ฆ„์ธ "spring"์ด ์ €์žฅ๋˜๋ฉฐ,

๋“ฑ๋ก ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด <form action="/members/new" method="post">์— ์˜ํ•ด

action์— ์ ํžŒ url(/members/new)์— Post ๋ฐฉ์‹์œผ๋กœ ์ž…๋ ฅํ•œ name์ด ๋„˜์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค.

 

Post ๋ฐฉ์‹์œผ๋กœ ๋„˜๊ฒผ๊ธฐ ๋•Œ๋ฌธ์—, memberController - create ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ

create์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ MemberForm์œผ๋กœ ์ด๋™

 

MemberForm์—๋Š” private String์œผ๋กœ name์ด ์„ ์–ธ๋˜์–ด ์žˆ๋‹ค.

์—ฌ๊ธฐ์— setName์„ ํ†ตํ•ด ์•„๊นŒ ๋„˜๊ฒจ์ค€ name์ธ "spring"์ด ์ €์žฅ๋œ๋‹ค.

์ดํ›„ getName์„ ํ†ตํ•ด ๋‚ด๊ฐ€ ์„ค์ •ํ•œ ์ด๋ฆ„์— ์ ‘๊ทผํ•˜๋ฉด ๋œ๋‹ค.

 

๋‹ค์‹œ create ๋ฉ”์„œ๋“œ๋กœ ๋Œ์•„์™€๋ณด๋ฉด member ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ ,

form.getName()์„ ํ†ตํ•ด ์ด๋ฆ„์„ ๋ถˆ๋Ÿฌ์™€์„œ member ์ด๋ฆ„์„ ์„ค์ •ํ•œ๋‹ค.

์ดํ›„ memberService.join์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋ฐฉ๊ธˆ ์ƒ์„ฑํ•œ member ๊ฐ์ฒด๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๊ฐ€์ž…์ด ์™„๋ฃŒ๋œ๋‹ค.

 

 


์ฃผ๋กœ ์•„๋ž˜ ๋ฐฉ์‹์œผ๋กœ GET/POST๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ : GET
๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ(๋“ฑ๋ก)ํ•  ๋•Œ : POST

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

 

# ํšŒ์› ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์กฐํšŒ ๊ธฐ๋Šฅ

java/hello/hellospring/controller/MemberController.java์— ์•„๋ž˜ ์ฝ”๋“œ ์ถ”๊ฐ€

@GetMapping("/members")
public String list(Model model) {
    List<Member> members = memberService.findMembers();
    model.addAttribute("members", members);
    return "members/memberList";
}

 

# ํšŒ์› ๋ฆฌ์ŠคํŠธ HTML

resources/templates/members/memberList.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<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> <!-- /container -->

</body>
</html>

 

 

# ์‹คํ–‰

ํšŒ์› ๊ฐ€์ž…

ํ”„๋กœ์ ํŠธ ์žฌ์‹คํ–‰ ํ›„ ํšŒ์›๊ฐ€์ž…์—์„œ spring1, spring2๋ฅผ ๋“ฑ๋กํ•ด์ค€๋‹ค.

 

ํšŒ์› ๋ชฉ๋ก

ํšŒ์› ๋ชฉ๋ก์— ๋“ค์–ด๊ฐ€๋ณด๋ฉด ๋“ฑ๋กํ•œ spring1, spring2๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ํ™•์ธ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ thymeleaf๊ฐ€ ๋ณธ๊ฒฉ์ ์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.

 

ํŽ˜์ด์ง€ ์†Œ์Šค(์ขŒ์ธก ์ด๋ฏธ์ง€)๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด ํƒœ๊ทธ ๋‚ด๋ถ€์— spring1, spring2๊ฐ€ ๋ Œ๋”๋ง ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์ด๋Š” ํ…œํ”Œ๋ฆฟ ์–ธ์–ด์—์„œ ์†Œ์Šค์ฝ”๋“œ(์šฐ์ธก ์ด๋ฏธ์ง€)์˜ ${members}๋ฅผ ์ฝ์–ด๋“ค์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

${members}๋Š” ๋ชจ๋ธ ์•ˆ์˜ ๊ฐ’์„ ๊บผ๋‚ธ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

์šฐ๋ฆฌ๋Š” ์ด์ „์— MemberController์—์„œ members(List)์— ๋ชจ๋“  ํšŒ์›์„ ์กฐํšŒํ•ด์„œ ์ „๋ถ€ ์ €์žฅํ•˜๊ณ 

model.addAttribute๋ฅผ ํ†ตํ•ด key์ธ "members"์— members ๋ฆฌ์ŠคํŠธ๋ฅผ ๋‹ด์•„๋‘์—ˆ๋‹ค.

์ด members๊ฐ€ ์šฐ์ธก ์ด๋ฏธ์ง€์˜ ์†Œ์Šค์ฝ”๋“œ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

 

๋‹ค์‹œ ์†Œ์Šค์ฝ”๋“œ๋กœ ๋Œ์•„์™€๋ณด๋ฉด, thymeleaf ๋ฌธ๋ฒ•์ธ each๋ฌธ์„ ํ†ตํ•ด

members ๋‚ด๋ถ€์˜ ํšŒ์› ๊ฐ์ฒด๋ฅผ ํ•˜๋‚˜์”ฉ ๊บผ๋‚ด์„œ member์— ๋Œ€์ž…ํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  th:text๋ฅผ ํ†ตํ•ด ๊ทธ member์˜ id์™€ name์„ ํ•˜๋‚˜์”ฉ ์ถœ๋ ฅํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋•Œ, id์™€ name๋„ private ํ•˜๊ธฐ ๋•Œ๋ฌธ์— Property ๋ฐฉ์‹(Getter/Setter๋ฅผ ํ†ตํ•œ ์ ‘๊ทผ)์œผ๋กœ ๊ฐ€์ ธ์˜จ๋‹ค.

 

 

# ์ฃผ์˜ํ•  ์ 

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

์‹ค๋ฌด์—์„œ ์ด๋Ÿฐ ์ผ์ด ๋ฐœ์ƒํ•˜๋ฉด ํฐ์ผ๋‚˜๊ธฐ ๋•Œ๋ฌธ์—(^^), ํŒŒ์ผ์ด๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค!

 

 

 

 

๋‚ด์šฉ ๋ฐ ์ด๋ฏธ์ง€ ์ถœ์ฒ˜ : ๊น€์˜ํ•œ์˜ ์Šคํ”„๋ง ์ž…๋ฌธ