๐Ÿ›๏ธ ์ƒํ’ˆ๋ชฉ๋ก ํŽ˜์ด์ง€ ๋งŒ๋“ค๊ธฐ (Thymeleaf)

EthAnalogยท2025๋…„ 8์›” 21์ผ

Spring Boot

๋ชฉ๋ก ๋ณด๊ธฐ
6/16
post-thumbnail

โœ… ์–ด๋–ค ๊ธฐ๋Šฅ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ธ๊ฐ€?

  • /list๋กœ ์ ‘์†ํ•˜๋ฉด ์ƒํ’ˆ ๋ชฉ๋ก ํŽ˜์ด์ง€(list.html)๋ฅผ ์ „์†ก
  • ์ปจํŠธ๋กค๋Ÿฌ์—์„œ Model์— ๋‹ด์€ ๋ฐ์ดํ„ฐ๋ฅผ Thymeleaf๋กœ ๋ฐ”์ธ๋”ฉ
  • ์ •์  HTML โ†’ ๋™์  ํŽ˜์ด์ง€๋กœ ์ „ํ™˜ํ•˜๋Š” ์ฒซ ๋‹จ๊ณ„ ํ™•๋ณด

๐Ÿ‘‰ ์™œ ์ด๊ฑธ ๋ฐฐ์›Œ์•ผ ํ•˜์ง€?

  • ์‡ผํ•‘๋ชฐ/๋ธ”๋กœ๊ทธ์˜ ๊ธฐ๋ณธ ํ๋ฆ„์€ ๋ชฉ๋ก โ†’ ์ƒ์„ธ
  • ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์•Œ์•„์•ผ DB ๋ฐ์ดํ„ฐ๋กœ ํ™”๋ฉด์„ ๋™์ ์œผ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Œ
  • ์ดํ›„ JPA ์—ฐ๋™ ์‹œ findAll() ๊ฒฐ๊ณผ๋ฅผ th:each๋กœ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐœํŒ

๐Ÿ“š ๊ฐœ๋… ์ •๋ฆฌ

ํ‚ค์›Œ๋“œ์„ค๋ช…
ControllerAPI๋ฅผ ๋‹ด๋Š” ํด๋ž˜์Šค. ์š”์ฒญ์„ ๋ฐ›์•„ ์–ด๋–ค ๋ทฐ๋ฅผ ๋ฐ˜ํ™˜ํ• ์ง€ ๊ฒฐ์ •
@GetMappingํŠน์ • URL์˜ GET ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” API ์ •์˜
templates/Thymeleaf ํ…œํ”Œ๋ฆฟ ์œ„์น˜. return "list" โ†’ templates/list.html ๋ Œ๋”
Model์ปจํŠธ๋กค๋Ÿฌ โ†’ ํ…œํ”Œ๋ฆฟ์œผ๋กœ ๋ณด๋‚ด๋Š” ๋ฐ์ดํ„ฐ ์ปจํ…Œ์ด๋„ˆ
th:textํƒœ๊ทธ ๋‚ด๋ถ€ ํ…์ŠคํŠธ๋ฅผ ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ๋กœ ์น˜ํ™˜
Thymeleaf์„œ๋ฒ„ ๋ฐ์ดํ„ฐ โ†’ HTML์— ์ฃผ์ž…ํ•˜๋Š” ํ…œํ”Œ๋ฆฟ ์—”์ง„

โš™๏ธ ๊ตฌํ˜„ ํ๋ฆ„ ๋ฐ ์ฝ”๋“œ

1) ์ปจํŠธ๋กค๋Ÿฌ ๋งŒ๋“ค๊ธฐ

๐Ÿ“„ src/main/java/com/apple/shop/item/ItemController.java

package com.apple.shop.item;

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

@Controller
public class ItemController {

    @GetMapping("/list")
    String list(Model model){
        model.addAttribute("name", "ํ™๊ธธ๋™"); // ์ž„์‹œ ๋ฐ์ดํ„ฐ
        return "list"; // templates/list.html
    }
}
  • ํŒจํ‚ค์ง€ ์„ ์–ธ์„ ๋งž์ถฐ์•ผ ๋‹ค๋ฅธ ๊ณณ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Œ (package com.apple.shop.item;)
  • return "list"์ฒ˜๋Ÿผ ํ™•์žฅ์ž ์ƒ๋žต ๊ถŒ์žฅ(Thymeleaf ๊ทœ์น™)

2) ํ…œํ”Œ๋ฆฟ(HTML) ๋งŒ๋“ค๊ธฐ

๐Ÿ“„ src/main/resources/templates/list.html

<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>์ƒํ’ˆ ๋ชฉ๋ก</title>
</head>
<body>
  <div>
    <img src="https://placehold.co/300" alt="thumb">
    <h4 th:text="${name}">๋ฐ”์ง€</h4>
    <p>7์–ต</p>
  </div>

  <div>
    <img src="https://placehold.co/300" alt="thumb">
    <h4>์…”์ธ </h4>
    <p>8์–ต</p>
  </div>
</body>
</html>
  • xmlns:th ์„ ์–ธ์œผ๋กœ Thymeleaf ์†์„ฑ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • ${name} โ† ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ณด๋‚ธ Model ๋ฐ์ดํ„ฐ

3) ์˜์กด์„ฑ ์ถ”๊ฐ€(์ตœ์ดˆ 1ํšŒ)

๐Ÿ“„ build.gradle

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
}
  • ์ถ”๊ฐ€ ํ›„ Load Gradle Changes โ†’ ์„œ๋ฒ„ ์žฌ์‹œ์ž‘

4) ๋™์ž‘ ํ™•์ธ

  1. ์„œ๋ฒ„ ์‹คํ–‰ โ†’ ๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:8080/list ์ ‘์†
  2. <h4>์— ํ™๊ธธ๋™์ด ๋ณด์ด๋ฉด ์„ฑ๊ณต(์ž„์‹œ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ ํ™•์ธ)
  3. ๋‹ค์Œ ๋‹จ๊ณ„: DB ์—ฐ๋™ ํ›„ th:each๋กœ ๋ชฉ๋ก ๋ฐ˜๋ณต ๋ Œ๋”๋ง

๐Ÿ’ก ์ด๋Ÿฐ ๊ณณ์— ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”

  • ์ƒํ’ˆ/๊ฒŒ์‹œ๊ธ€/๊ณต์ง€ ๋ชฉ๋ก ํŽ˜์ด์ง€
  • ํ•„ํ„ฐยท์ •๋ ฌยทํŽ˜์ด์ง€๋„ค์ด์…˜(์ดํ›„ JPA์™€ ํ™•์žฅ)
  • ๋ชฉ๋ก โ†’ ์ƒ์„ธ๋กœ ๋งํฌ ์—ฐ๊ฒฐ

โœ๏ธ ๊ฐœ์ธ ์ •๋ฆฌ ๋ฐ ํšŒ๊ณ 

  • Controller โ†’ Model โ†’ Template ๋ฐ์ดํ„ฐ ํ๋ฆ„ ์ฒด๋“
  • ์ •์  HTML์—์„œ ๋™์  ๋ Œ๋”๋ง์œผ๋กœ ์ „ํ™˜
  • ๋‹ค์Œ์€ DB์—์„œ findAll() ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„ th:each๋กœ ๋ฐ˜๋ณต ์ถœ๋ ฅ

๐Ÿ”‘ ์˜ค๋Š˜ ๋ฐฐ์šด ํ•ต์‹ฌ 3์ค„ ์š”์•ฝ

  1. /list API์—์„œ Model๋กœ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ โ†’ list.html์—์„œ Thymeleaf ๋ฐ”์ธ๋”ฉ
  2. ํ…œํ”Œ๋ฆฟ์€ ๋ฐ˜๋“œ์‹œ templates/์— ๋‘๊ณ  return "๋ทฐ์ด๋ฆ„"์œผ๋กœ ๋ Œ๋”
  3. ์ดํ›„ DB ๋ฐ์ดํ„ฐ๋„ ๊ฐ™์€ ํŒจํ„ด์œผ๋กœ ์‰ฝ๊ฒŒ ํ™•์žฅ ๊ฐ€๋Šฅ

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