서버사이드 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>