본문 바로가기
HTML+JavaScript

Thymeleaf

by chogigang 2023. 3. 3.

가공한 데이터를 이용하여 화면을 만드는 방법입니다.

 

화면을 동적으로 만들려면 템플릿 엔진을 사용해야 합니다. 미리 정의된 템플릿(Template)을 만들고 동적으로 HTML페이지를 만들어서 클라이언트에 전달하는 방식입니다. 요청이 올 때마다 서버에서 새로운 HTML 페이지를 만들어 주기 때문에 서버 사이드 렌더링 방식이라고 합니다.

 

서버 사이드 템플릿 엔진으로는 Thymeleaf,JSP,Freemarker,Groovy,Mustache 등 있습니다.

어떤 것을 사용해도 만들 수 있지만 스프링에서 권장하는 Thymeleaf를 사용을 많이 합니다.

Thymeleaf의 가장 큰 장점은 natural templates 입니다 

Thymeleaf를 사용할 때 Thymeleaf 문법을 포함하고 있는 html 파일을 서버 사이드 렌더링을 하지 않고 브라우저에 띄어도

 정상적인 화면을 볼 수 있습니다. Thymeleaf의 확장자명은.html이며 ,Thymeleaf의 문법은 html태그 안쪽에 속성으로 사용됩니다.

 

 

 

 

 

 

Thymeleaf 문법

대부분의 html 속성을  th:xxx 로 변경할 수 있습니다.

ex: th:text="${변수명}"

 

표현 설명 예제
@{ ... } URL 링크 표현식 th:href="@{/css/bootstrap.min.css}"
th:href="@{/{itemId}/edit(itemId=${item.id})}"
| ... | 리터럴 대체 th:text="|Hi ${user.name}!|"
(= th:text="'Hi '+${user.name}+'!'"
${ ... } 변수 th:text=${user.name}
th:each 반복 출력 <tr th:each="item: ${items}">
  <td th:text="${item.price}">100</td>
</tr>
th:if
th:unless
조건문 <tr th:if="${status.even}" th:text="짝수"></td>
<td th:unless= "${status.even}" th:text="홀수">
</td>
th:switch
th:case
조건문과 같다.    <td th:switch="${status.even}">
<span th:case=true>짝수</span>
<span th:case=false>홀수</span>
th:href 링크
 <a th:href="@{/thymeleaf/ex01}">
예제1 페이지 이동</a>
*{ ... } 선택 변수 <tr th:object="${items}">
  <td th:text="*{price}">100</td>
</tr>
#{ ... } 메시지. properties 같은 외부 자원에서 코드에 해당하는 문자열 get. th:text="#{member.register}"

 

 

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p th:text="${data}">Hello Thymeleaf!!</p>
</body>
</html>

 

 

@Controller
@RequestMapping(value="/thymeleaf")
public class ThymeleafExController {

    @GetMapping(value = "/ex01")
    public String thymeleafExample01(Model model) {
        model.addAttribute("data", "타임리프 예제 입니다.");
        return "thymeleafEx/thymeleafEx01";
    }

1.클라이언트의 요청에 대해서 어떤 컨트롤러가 처리할지는 @RequestMapping+@GetMapping  어노테이션으로 url에 

"/thymeleaf" 경로로 오는 요청을 ThymeleafExController 가 처리하도록 합니다.

2.model 객체를 이용해 뷰에 전달한 데이터를 key,value 구조로 넣어줍니다.

3.templates 폴더를 기준으로 뷰의 위치와 이름(thymeleafEx01)을 반환합니다.

 

 

 

 

th:text 예제 심화

 

dto 패키지를 생성 후 뷰 영역에서 사용할 ItemDto 클래스를 생성합니다. 데이터를 주고받을 때는 Entity 클래스 자체를 반환하면 안 되고 데이터 전달용 객체(Data Transfer Object) 를 생성해서 사용해야 합니다.

데이터베이스의 설계를 외부에 노출할 필요도 없으며, 요청과 응답 객체가 항상 엔티티와 같지 않기 때문입니다.

 

Getter
@Setter
public class ItemDto {

    private Long id;

    private String itemNm;

    private Integer price;

    private String itemDetail;

    private String sellStatCd;

    private LocalDateTime regTime;

    private LocalDateTime updateTime;


}

 

 

Controller

 

@GetMapping(value = "/ex02")
public String thymeleafExample02(Model model) {
    ItemDto itemDto = new ItemDto();
    itemDto.setItemDetail("상품 상세 설명");
    itemDto.setItemNm("테스트 상품1");
    itemDto.setPrice(10000);
    itemDto.setRegTime(LocalDateTime.now());

    model.addAttribute("itemDto", itemDto);
    return "thymeleafEx/thymeleafEx02";
}

 

HTML

 

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>상품 데이터 출력 예제</h1>
<div>
    상품명 : <span th:text="${itemDto.itemNm}"></span>
</div>
<div>
    상품상세설명 : <span th:text="${itemDto.itemDetail}"></span>
</div>
<div>
    상품등록일 : <span th:text="${itemDto.regTime}"></span>
</div>
<div>
    상품가격 : <span th:text="${itemDto.price}"></span>
</div>
</body>
</html>

 

 

th:each 예제

 

위 표와 같이 타임리프 반복문 입니다.

 

@GetMapping(value = "/ex03")
public String thymeleafExample03(Model model) {
    List<ItemDto> itemDtoList = new ArrayList<>();
    for (int i = 1; i <= 10; i++) {
        ItemDto itemDto = new ItemDto();
        itemDto.setItemDetail("상품 상세 설명" + i);
        itemDto.setItemNm("테스트 상품" + i);
        itemDto.setPrice(1000 * i);
        itemDto.setRegTime(LocalDateTime.now());

        itemDtoList.add(itemDto);

    }

 

 

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<h1>상품 리스트 출력 예제</h1>

<table border="1">
  <thead>
  <tr>
    <td>순번</td>
    <td>상품명</td>
    <td>상품설명</td>
    <td>가격</td>
    <td>상품등록일</td>
  </tr>
  </thead>
  <tbody>
  <tr th:each="itemDto, status: ${itemDtoList}">
    <td th:text="${status.index}"></td>
    <td th:text="${itemDto.itemNm}"></td>
    <td th:text="${itemDto.itemDetail}"></td>
    <td th:text="${itemDto.price}"></td>
    <td th:text="${itemDto.regTime}"></td>
  </tr>
  </tbody>
</table>

</body>
</html>

 

 

 

th:if ,th:unless 예제

조건문 입니다.

@GetMapping(value = "/ex04")
public String thymeleafExample04(Model model) {
    List<ItemDto> itemDtoList = new ArrayList<>();

    for (int i = 1; i <= 10; i++) {
        ItemDto itemDto = new ItemDto();
        itemDto.setItemDetail("상품 상세 설명");
        itemDto.setItemNm("테스트 상품" + i);
        itemDto.setPrice(1000 * i);
        itemDto.setRegTime(LocalDateTime.now());

        itemDtoList.add(itemDto);
    }
    model.addAttribute("itemDtoList", itemDtoList);
    return "thymeleafEx/thymeleafEx04";

 

status에는 현재 반복문에 대한 정보가 존재합니다. 인덱스가 짝수일 경우 status.even은 true가 됩니다. 즉 현재 인덱스가 짝수라면 순번에 '짝수'를 출력해줍니다.

현재 인덱스가 짝수가 아닐 경우 즉,홀수일 경우 순번에'홀수'를 출력해줍니다.

 

<table border="1">
  <thead>
  <tr>
    <td>순번</td>
    <td>상품명</td>
    <td>상품설명</td>
    <td>가격</td>
    <td>상품등록일</td>
  </tr>
  </thead>
  <tbody>
  <tr th:each="itemDto, status: ${itemDtoList}">
    <td th:switch="${status.even}">
      <span th:case=true>짝수</span>
      <span th:case=false>홀수</span>
    </td>
    <td th:text="${itemDto.itemNm}"></td>
    <td th:text="${itemDto.itemDetail}"></td>
    <td th:text="${itemDto.price}"></td>
    <td th:text="${itemDto.regTime}"></td>
  </tr>
  </tbody>
</table>

 

 

 

th:href 예제

 

@GetMapping(value = "/ex05")
public String thymeleafExample05() {
    return "thymeleafEx/thymeleafEx05";

}

 


<h1>Thymeleaf 링크처리 예제 페이지</h1>
<div>
    <a th:href="@{/thymeleaf/ex01}">예제1 페이지 이동</a>
</div>
<div>
    <a th:href="@{https://www.thymeleaf.org/}">thymeleaf 공식 페이지 이동</a>
</div>
<div>
    <a th:href="@{/thymeleaf/ex06(param1 = '파라미터 데이터1',
    param2 = '파라미터 데이터2')}">thymeleaf 파라미터 전달 </a>
</div>

 

 

 

파라미터 값을 전달해야 하는 경우도 처리 가능합니다.

 

@GetMapping(value = "/ex06")
public String thymeleafExample06(String param1, String param2, Model model) {
    model.addAttribute("param1", param1);
    model.addAttribute("param2", param2);
    return "thymeleafEx/thymeleafEx06";
}

 

 

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1> 파라미터 전달 예제</h1>
<div th:text="${param1}"></div>
<div th:text="${param2}"></div>
</body>
</html>

 

 

 

 

보통 웹사이트를 만들려면 header,footer,menu 등 공통적인 페이지 구성 요소들이 있습니다.

이런 영역들을 각가의 페이지마다 같은 소스코드를 넣는다면 변경이 일어날 때마다 이를 포함하고

있는 모든 페이지를 수정해야 할 것입니다. Thymeleaf 의 페이지 레이아웃 기능을 사용한다면 공통 요소 관리를 

쉽게 관리 할 수 있습니다.

 

 

 

 

'HTML+JavaScript' 카테고리의 다른 글

flutter 공식문서 예제 들고오기  (0) 2024.06.18
Bootstrap  (0) 2023.03.03