Spring/SpringMVC

상품 목록 - 타임리프

느리지만 꾸준하게 2022. 5. 3. 15:20

컨트롤러 뷰 템플릿 만들자.

// BasicItemController Class

package hello.itemservice.web.basic;


import hello.itemservice.domain.item.Item;
import hello.itemservice.domain.item.ItemRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.PostConstruct;
import java.util.List;

@Controller
@RequestMapping("/basic/items")
@RequiredArgsConstructor
public class BasicItemController {

    private final ItemRepository itemRepository;

    @GetMapping
    public String items(Model model) {
        List<Item> items = itemRepository.findAll();
        model.addAttribute("items", items);
        return "basic/items";
    }

    /**
     * 테스트용 데이터 추가
     */
    @PostConstruct
    public void init() {
        itemRepository.save(new Item("itemA", 10000, 10));
        itemRepository.save(new Item("itemb", 20000, 20));
    }

}

 

 

thymeleaf 문법으로 동적으로 items.html 파일을 만들자.

 

아래와 같이 타임리프 문법으로 지정해주면 경로가 href ../css 가 아닌 css/~ 이렇게 나온다.

// items.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <link th:href="@{/css/bootstrap.min.css}"
            href="../css/bootstrap.min.css" rel="stylesheet">
</head>

 

상품등록도 아래와 같이 th:onclick ~ 작성해주면 반영이 잘 된다.

<div class="row">
    <div class="col">
        <button class="btn btn-primary float-end"
                onclick="location.href='addForm.html'"
                th:onclick="|location.href='@{/basic/items/add}'|"
                type="button">상품 등록</button>
    </div>
</div>

 

 

 

프로퍼티 접근법으로 작성을 해보면 아래 부분을 작성해보자.

<!-- 기존에 여기서 -->

<tr>
    <td><a href="item.html">2</a></td>
    <td><a href="item.html">테스트 상품2</a></td>
    <td>20000</td>
    <td>20</td>
</tr>

 

 

th 문법을 쓰자.

 

<!-- 이걸로 바꾼다. -->

<tbody>
<tr th:each="item : ${items}">
    <td><a href="item.html" th:text="${item.id}">회원id</a></td>
    <td><a href="item.html" th:text="${item.itemName}">테스트 상품1</a></td>
    <td th:text="${item.price}">10000</td>
    <td th:text="${item.quantity}">10</td>
</tr>
</tbody>

 

타임리프에서 아래문법 신경쓰자.

  • @{
<tbody>
<tr th:each="item : ${items}">
    <td><a href="item.html" th:href="@{/basic/items/{itemId}(itemId=${item.id})}" th:text="${item.id}">회원id</a></td>
    <td><a href="item.html" th:href="@{/basic/items/{itemId}(itemId=${item.id})}" th:text="${item.itemName}">테스트 상품1</a></td>
    <td th:text="${item.price}">10000</td>
    <td th:text="${item.quantity}">10</td>
</tr>
</tbody>

basic/items/1이라고 잘 나온다.

 

 

basic package에 items.html 완성

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <link th:href="@{/css/bootstrap.min.css}"
            href="../css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container" style="max-width: 600px">
    <div class="py-5 text-center">
        <h2>상품 목록</h2>
    </div>
    <div class="row">
        <div class="col">
            <button class="btn btn-primary float-end"
                    onclick="location.href='addForm.html'"
                    th:onclick="|location.href='@{/basic/items/add}'|"
                    type="button">상품 등록</button>
        </div>
    </div>
    <hr class="my-4">
    <div>
        <table class="table">
            <thead>
            <tr><th>ID</th>
                <th>상품명</th>
                <th>가격</th>
                <th>수량</th>
            </tr>
            </thead>
            <tbody>
            <tr th:each="item : ${items}">
                <td><a href="item.html" th:href="@{/basic/items/{itemId}(itemId=${item.id})}" th:text="${item.id}">회원id</a></td>
                <td><a href="item.html" th:href="@{/basic/items/{itemId}(itemId=${item.id})}" th:text="${item.itemName}">테스트 상품1</a></td>
                <td th:text="${item.price}">10000</td>
                <td th:text="${item.quantity}">10</td>
            </tr>
            </tbody>
        </table>
    </div>
</div> <!-- /container -->

</body>
</html>

 

리터럴 대체로 아래와 같이 해줄 수도 있다.

<tr th:each="item : ${items}">
    <td><a href="item.html" th:href="@{/basic/items/{itemId}(itemId=${item.id})}" th:text="${item.id}">회원id</a></td>
    <td><a href="item.html" th:href="@{|/basic/items/${item.id}|}" th:text="${item.itemName}">테스트 상품1</a></td>
    <td th:text="${item.price}">10000</td>
    <td th:text="${item.quantity}">10</td>
</tr>

 

 

타임리프는 화면 html의 모양을 그대로 살리면서 뷰 템플릿으로 렌더링 될 때만 조금씩 치환을 한다. 그래서 화면을 크게 깨트리지 않는다.

<tbody>
<tr th:each="item : ${items}">
    <td><a href="item.html" th:href="@{/basic/items/{itemId}(itemId=${item.id})}" th:text="${item.id}">회원id</a></td>
    
    <!-- 이 부분 변경,  || 이용 -->
    <td><a href="item.html" th:href="@{|/basic/items/${item.id}|}" th:text="${item.itemName}">테스트 상품1</a></td>
    <td th:text="${item.price}">10000</td>
    <td th:text="${item.quantity}">10</td>
</tr>
</tbody>

 

 

타임리프 간단히 알아보기

 

타임리프 사용 선언

<html xmlns:th="http://www.thymeleaf.org">

 

아래 내용을 기억하자

 

  • 속성 변경  - th:href

 

  • 타임리프 핵심 - 대부분의 HTML 속성을 th:xxx 로 변경할 수 있다

 

  • URL 링크 표현식 - @{...}

 

  • 속성 변경 - th:onclick - 상품 등록 폼으로 이동

 

  • 리터럴 대체 - |...|

 

  • 반복 출력 - th:each

 

  • 변수 표현식 - ${...}

 

  • 내용 변경 - th:text

 

  • URL 링크 표현식2 - @{...}

 

  • URL 링크 간단히

=> 타임리프는 순수 HTML을 그대로 유지하면서 뷰 템플릿도 사용할 수 있는 타임리프의 특징을 가진 네츄럴 템플릿이다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

<출처 김영한: 스프링 MVC 1편 - 벡앤드 웹 개발 핵심 기술>

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard

 

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의

웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -

www.inflearn.com