๐Ÿ“Œ Spring Boot - Thymeleaf ์‚ฌ์šฉ ์ •๋ฆฌ

My Pale Blue Dotยท2025๋…„ 5์›” 9์ผ
0

SPRING BOOT

๋ชฉ๋ก ๋ณด๊ธฐ
11/40
post-thumbnail

๐Ÿ“… ๋‚ ์งœ

2025-05-09

๐Ÿ“ ํ•™์Šต ๋‚ด์šฉ

1๏ธโƒฃ Thymeleaf๋ž€?

โœ… ์ •์˜

Thymeleaf๋Š” HTML/XML ๋ฌธ๋ฒ•์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ํ…œํ”Œ๋ฆฟ ์—”์ง„์ž…๋‹ˆ๋‹ค. Spring Boot์™€์˜ ์—ฐ๋™์„ฑ์ด ๋›ฐ์–ด๋‚˜ View Layer ๊ตฌ์„ฑ์— ๋งŽ์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

โœ… ํŠน์ง• ์š”์•ฝ

  • HTML ํŒŒ์ผ ๊ทธ๋Œ€๋กœ ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ™•์ธ ๊ฐ€๋Šฅ (HTML ์นœํ™”์  ๋ฌธ๋ฒ•)
  • Spring MVC์˜ Model ๊ฐ์ฒด์™€ ์‰ฝ๊ฒŒ ์—ฐ๊ฒฐ
  • ์กฐ๊ฑด๋ฌธ, ๋ฐ˜๋ณต๋ฌธ, ๋งํฌ ์ƒ์„ฑ, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ณ€์ˆ˜ ๋ฐ”์ธ๋”ฉ ๋“ฑ ๋‹ค์–‘ํ•œ ํ‘œํ˜„์‹ ์ง€์›
  • @ModelAttribute์™€ ํ•จ๊ป˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ์‰ฝ๊ฒŒ ์ „๋‹ฌ ๊ฐ€๋Šฅ

2๏ธโƒฃ Gradle ์˜์กด์„ฑ ์„ค์ •

implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'

3๏ธโƒฃ application.yml ์„ค์ • (JSP ํ˜ผ์šฉ ํฌํ•จ)

spring:
  thymeleaf:
    prefix: classpath:/templates/
    view-names: th/*       # th/๋กœ ์‹œ์ž‘ํ•˜๋Š” view๋Š” thymeleaf๋กœ ์ฒ˜๋ฆฌ
    suffix: .html
    mode: HTML5
    cache: false

  mvc:
    view:
      prefix: /WEB-INF/views/
      suffix: .jsp         # JSP ํ˜ผ์šฉ ์‹œ ์„ค์ •

โœ… ViewResolver ์šฐ์„ ์ˆœ์œ„๋ฅผ ๋ช…ํ™•ํžˆ ์„ค์ •ํ•ด ์ถฉ๋Œ ๋ฐฉ์ง€


4๏ธโƒฃ HTML ํ…œํ”Œ๋ฆฟ ์˜ˆ์ œ (test1.html)

<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org/">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <!-- ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ ์ถœ๋ ฅ -->
    NAME : <span th:text="${name}"></span>  <hr/>
    MEMO : <span th:text="${memo}"></span>  <hr/>
    MEMO.ID : <span th:text="${memo.id}"></span>  <hr/>
    MEMO.TEXT : <span th:text="${memo.text}"></span>  <hr/>
    MEMO.WRITER : <span th:text="${memo.writer}"></span>  <hr/>

    <!-- ์กฐ๊ฑด๋ฌธ ์ฒ˜๋ฆฌ -->
    <th:block th:if="${isAuth}">
        <div>๋กœ๊ทธ์ธ ์ƒํƒœ์ž…๋‹ˆ๋‹ค</div>
    </th:block>
    <th:block th:unless="${isAuth}">
        <div>๋กœ๊ทธ์•„์›ƒ ์ƒํƒœ์ž…๋‹ˆ๋‹ค</div>
    </th:block>

    <hr/>

    <!-- ๋ฐ˜๋ณต๋ฌธ ์ฒ˜๋ฆฌ -->
    <th:block>
        <div th:each="memo : ${memoList}">
            <span th:text="${memo.id}"></span> :
            <span th:text="${memo.text}"></span>
        </div>
    </th:block>

    <hr/>

    <!-- ํŒŒ๋ผ๋ฏธํ„ฐ ์ „๋‹ฌ ๋ฐฉ์‹ -->
    <a th:href="@{/th/param1(id=${memo.id},text='aaa',writer='bbb')}">์ด๋™ํ•˜๊ธฐ</a> |
    <a th:href="@{/th/param2/{id}/{text}/{writer}(id=${memo.id},text='aaa',writer='bbb')}">์ด๋™ํ•˜๊ธฐ2</a>

    <!-- JavaScript ๋ณ€์ˆ˜ ๋ฐ”์ธ๋”ฉ -->
    <script th:inline="javascript">
        const name = [[ ${name} ]];
        const memo = [[ ${memo} ]];
        const memoList = [[ ${memoList} ]];
        console.log('name', name);
        console.log('memo', memo);
        console.log('memoList', memoList);
    </script>
</body>
</html>

โœ… ์„ค๋ช…

  • th:text: ๋ชจ๋ธ ๊ฐ’ ์ถœ๋ ฅ
  • th:if, th:unless: ์กฐ๊ฑด ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ
  • th:each: ๋ฐ˜๋ณต๋ฌธ
  • th:href: URL ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ
  • th:inline="javascript": JS ๋‚ด์— ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ ์ฃผ์ž… ๊ฐ€๋Šฅ

5๏ธโƒฃ Controller ์˜ˆ์ œ (ThymeleafTestController.java)

@Controller
@Slf4j
@RequestMapping("/th")
public class ThymeleafTestController {

    @Autowired
    private MemoRepository memoRepository;

    @GetMapping("/test1")
    public void test1(Model model){
        log.info("GET /th/test1....");

        // ๋ฌธ์ž์—ด ๊ฐ’ ์ „๋‹ฌ
        model.addAttribute("name", "hong");

        // DTO ๊ฐ์ฒด ์ƒ์„ฑ ๋ฐ ์ฃผ์ž…
        MemoDto memo = new MemoDto();
        memo.setId(111);
        memo.setText("aaa");
        memo.setWriter("aaa@naver.com");
        model.addAttribute("memo", memo);

        // ๋กœ๊ทธ์ธ ์—ฌ๋ถ€ ๊ฐ’
        model.addAttribute("isAuth", false);

        // ์ „์ฒด ๋ฉ”๋ชจ ๋ฆฌ์ŠคํŠธ ์ „๋‹ฌ
        List<Memo> memoList = memoRepository.findAll();
        model.addAttribute("memoList", memoList);
    }

    // ์ฟผ๋ฆฌ์ŠคํŠธ๋ง ํŒŒ๋ผ๋ฏธํ„ฐ ์ž๋™ ๋ฐ”์ธ๋”ฉ
    @GetMapping("/param1")
    public void param1(@ModelAttribute MemoDto memoDto){
        log.info("GET /th/param1..." + memoDto);
    }

    // PathVariable ๋ฐ”์ธ๋”ฉ๋„ @ModelAttribute๋กœ ์ˆ˜์ง‘ ๊ฐ€๋Šฅ
    @GetMapping("/param2/{id}/{text}/{writer}")
    public void param2(@ModelAttribute MemoDto memoDto){
        log.info("GET /th/param2..." + memoDto);
    }

    // ๋‹จ์ˆœ ํŽ˜์ด์ง€ ์ด๋™
    @GetMapping("/test2")
    public void test2(){
        log.info("GET /th/test2...");
    }
}

โœ… ์„ค๋ช…

  • Model ๊ฐ์ฒด๋กœ HTML์— ๋ฐ์ดํ„ฐ ์ „๋‹ฌ
  • @ModelAttribute๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ ์ž๋™ ๋งคํ•‘
  • void ๋ฆฌํ„ด ์‹œ ์š”์ฒญ ๊ฒฝ๋กœ์™€ ๋™์ผํ•œ ํ…œํ”Œ๋ฆฟ(.html) ์ž๋™ ํ˜ธ์ถœ๋จ

๐Ÿ”ฅ ์ •๋ฆฌ

  • Thymeleaf๋Š” Spring Boot์—์„œ HTML ํ…œํ”Œ๋ฆฟ ๋ Œ๋”๋ง์— ์ตœ์ ํ™”๋œ ์—”์ง„
  • ViewResolver๋ฅผ ๋‚˜๋ˆ ์„œ JSP์™€ ํ˜ผ์šฉ ๊ฐ€๋Šฅ
  • Controller โ†’ Model โ†’ View ๊ตฌ์กฐ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ด€๋ฆฌ
  • ์กฐ๊ฑด๋ฌธ, ๋ฐ˜๋ณต๋ฌธ, ๋งํฌ, JS ์—ฐ๋™๊นŒ์ง€ ํ™•์žฅ์„ฑ ๋งค์šฐ ๋›ฐ์–ด๋‚จ

๐Ÿ”— ์ฐธ๊ณ  ์ž๋ฃŒ


profile
Here, My Pale Blue.๐ŸŒ

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