타임리프

김남연·2025년 8월 17일

SpringMVC

목록 보기
5/8

Thymeleaf

서버사이드 HTML렌더링
-> 타임리프는 백엔드 서버에서 HTML을 동적으로 렌더링 하는 용도로 사용된다.
네츄럴템플릿
-> 순수 HTML을 최대한 유지하는 특성이 있다. 웹 브라우저에서 파일을 직접 열어도 내용을 확인할 수 있고 서버를 통해 뷰 템플릿을 거치면 동적으로 변경된 결과를 확인할 수 있다.

타임리프 사용 선언

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

텍스트 출력

@Controller
@RequestMapping("/basic")
public class BasicController {

	@GetMapping("/text-basic")
	public String textBasic(Model model) {
    	model.addAttribute("data", "Hello Spring");
        return "basic/text-basic";
    }
}
<h1>컨텐츠에 데이터 출력하기</h1>
<ul>
  <li>th:text 사용 <span th:text="${data}"></span></li>
  <li>컨텐츠 안에서 직접 출력하기 = [[${data}]]</li>
</ul>

변수

변수 표현식 : S{...}

<h1>SpringEL 표현식</h1>
<ul>Object
  <li>${user.usename} = <span th:text="${user.username>"></span></li>
  <li>${user.usename} = <span th:text="${user['username']>"></span></li>
  <li>${user.usename} = <span th:text="${user.getUsername()>"></span></li>
  <!-- 모두 같은 표현 -->
</ul>

user의 username 프로퍼티 접근하는 방법이다

지역변수

<h1>지역변수 - th:with</h1>
<div th:with = "first=${users[0]}">
  <p>처음 사람의 이름은 <span th:text="${first.username}"></span></p>
</div>

### URL 링크
```html 
<h1>URL링크</h1>
<ul>
  <li><a th:href="@{/hello}> basic url </a></li>
    <li><a th:href="@{/hello(param1=${param1}, param2=${param2})}> query param</a></li>
  <li><a th:href="@{/hello/{param1}/{param2}(param1=@{param1},param2=${param2})}">path variable </a></li>
  <li><a th:href="@{/hello/{param1}(param1=${param1},param2=${param2})}">path varible + query parameter</a></li>
</ul>

단순한 URL, 쿼리파라미터, 경로 변수, 경로 변수 + 쿼리파라미터 방식 모두 가능하다

리터럴

문자 : 'hello'
숫자 : 10
불린 : true, false
null : null

<h1> 리터럴 </h1>
<ul>
  <li> 'hello world' = <span th:text="'hello world'"></span></li>
  <li> 'hello ' + ${data} = <span th:text="'hello ' + ${data}"></span></li>
  <li> 리터럴대체 |hello ${data}| = <span th:text = "|hello ${data}|"></span></li>
</ul>

리터럴 대체문법을 사용하면 템플릿을 사용하는 것 처럼 편리하다

연산

<ul>
  <li>산술 연산
    <ul>
      <li>10+2 = <span th:text="10+2"></span></li>
    </ul>
  </li>
  <li>비교 연산
    <ul>
      <li>1 > 10 = <span th:text="1 gt 10"></span></li>
      <li>1 >= 10 = <span th:text="1 >= 10"></span></li>
      <li>1 < 10 = <span> th:text="1 lt 10"></span></li>
    </ul>
  </li>
  <li>조건식
    <ul>
      <li>10%2==0 ? <span th:text = "(10%2==0)? '짝수':'홀수'"></span></li>
    </ul>
  <li>Elvis연산자
    <ul>
      <li>${data}?: '데이터가 없습니다' <span th:text = "${data}?: '데이터가 없습니다'"></span></li>
    </ul>
</ul>

산술 연산은 항상 쓰듯이
비교연산은 태크때문에 gt lt만 주의
조건식도 항상 쓰듯이
Elvis는 null인 경우를 고려하여 안전하게 값을 출력할 때 사용한다

속성 값 설정

th: 속성을 지정하면 타임리프는 기존 속성을 th: 로 지정한 속성으로 대체한다. 기존 속성이 없으면 새로 만든다.

반복

<h1>기본 테이블</h1>
<table border="1">
  <tr th:each = "user : ${users}">
    <td th:text="${user.username}">username</td>
    <td th:text="${user.age}">0</td>
  </tr>
</table>

${users}컬렉션에서 값을 하나씩 꺼내 왼쪽 변수 user에 담아 태그를 반복 실행한다

조건

<table border="1">
  <tr th:each = "user : ${users}">
    <td>
      <span th:text="'미성년자'" th:if="${user.age lt 20}"></span>
      <span th:text="'미성년자'" th:unless="${user.age ge 20}"></span>
    </td>
  </tr>
</table>

if, unless 조건이 맞지않으면 태그 자체를 랜더링하지않는다

입력 폼 처리

@GetMapping("/add")
public String addForm(Model model) {
	model.addAttribute("item", new Item());
    return "form/addForm";
}
<form action="item.html" th:action th:object="${item}" method="post">
  <div>
    <label for = "itemName">상품명</lable>
    <input type = "text" th:field="*{itemName}" placeholder="이름을 입력하세요">
  </div>
  <div>
    <label for = "price">가격</lable>
    <input type = "text" th:field="*{price}" placeholder="가격을 입력하세요">
  </div>

th:action
-> 별다른 지정을 하지않으니 뷰를 렌더링한 컨트롤러를 다시 호출한다

th:object
-> form 태그에서 사용할 객체를 지정한다. 선택 변수식 *{...}를 적용할 수 있다

th:field="*{itemName}"
-> th:field="${item.itemName}"과 같다
form 태그의 id, name, value를 th:field에서 지정한 변수의 이름과 값으로 바인딩한다.

체크박스

<div>
  <input type = "checkbox" th:field="*{open}">
  <label for = "open"> 판매 오픈 </label>
</div>

html에서는 체크박스가 체크되지않으면 false값을 보내지않고 null이 전달되어 체크되었는지 확인하기 번거롭다.
타임리프에서 프로퍼티를 바인딩하면 이를 spring이 알아서 처리하고 true false값을 전달한다

라디오 버튼

<div>
  <div>상품 종류</div>
  <div th:each="type : ${itemType}">
    <input type = "radio" th:field="*{itemType}" th:value="${type.name()">
    <label th:for ="${#ids.prev('itemType')}" th:text="${type.description}"> book 	  </label>
  </div>
</div>

0개의 댓글