본문으로 바로가기

 개요


타임리프(Thymeleaf) 템플릿에서는 for문 while 등과 유사한 반복(iteration) 처리를 위해 th:each 를 사용 합니다. 

루프 처리 중 상태를 추적하는 데 유용한 메커니즘인 status 변수가 제공되어 index, count 등을 쉽게 얻을 수도 있습니다.


다만 loop를 원천적으로 break를 하거나 반복처리를 하면서 어떤 값을 더해 다른 곳에서 사용하는 것이 불가하는 등 제약사항들이 있지만 우리는 Thymeleaf가  view Template engine이라는걸 명심해야 합니다! 


JSTL등 에서 처리하듯이 Business logic을 view에 녹이는 것은 지양 해야하며 이런 비즈니스로직이 들어가는 부분은 서버에서 처리한 뒤 view Template 에서는 완성된 데이터를 "보여주는 것" 에 집중하는게 바람직하겠습니다.


 th:each 


 반복 하려는 html 엘리먼트에 th:each 속성을 사용하여 콜렉션(Collection) 을 반복하며 화면을 처리 할 수 있습니다.

/* Entity Class */
public class Product{
	private int seq;
	private String name;
	private int price;
	private int quantity;
}
/* Java Controller */
@RequestMapping(value = "/thymeleaf/iteration", method = { RequestMethod.POST, RequestMethod.GET })
public String Thymeleaf(Model model){
	List<Product> productList = new ArrayList<>();
	// constructor >> seq, name, price, quantity
	productList.add(new Product(1,"사과",1000,10));
	productList.add(new Product(2,"배",2000,16));
	productList.add(new Product(3,"초콜릿",1000,3));
	productList.add(new Product(4,"치킨",15000,1));
	//add data to view
	model.addAttribute("productList",productList);
	return "thymeleaf/iteration";
}
<!-- html (Thymeleaf) --> 
<table class="tb_col">
	<tr>
	<th>seq</th>
	<th>name</th>
	<th>price</th>
	<th>quantity</th>
	</tr>
	<tr th:each="product : ${productList}">
		<td th:text="${product.seq}"></td>
		<td th:text="${product.name}"></td>
		<td th:text="${product.price}"></td>
		<td th:text="${product.quantity}"></td>
	</tr>
</table>

▼▼▼▼▼ 결과(HTML)

<table class="tb_col">
	<tr>
		<th>seq</th>
		<th>name</th>
		<th>price</th>
		<th>quantity</th>
	</tr>
	<tr>
		<td>1</td>
		<td>사과</td>
		<td>1000</td>
		<td>10</td>
	</tr>
	<tr>
		<td>2</td>
		<td>배</td>
		<td>2000</td>
		<td>16</td>
	</tr>
	<tr>
		<td>3</td>
		<td>초콜릿</td>
		<td>1000</td>
		<td>3</td>
	</tr>
	<tr>
		<td>4</td>
		<td>치킨</td>
		<td>15000</td>
		<td>1</td>
	</tr>
</table>


 #numbers.sequence 


컬렉션 없이 단순 반복 처리를 하고 싶다면 Numbers Class(org.thymeleaf.expression.Numbers)의 Utility method인  #numbers.sequence을 사용하여 먼저 원하는 반복 횟수 만큼의 배열을 생성한 뒤 th:each 의 컬렉션에 넣어 주시면 됩니다.
/* Create a sequence (array) of integer numbers going from x to y */
${#numbers.sequence(from,to)}
${#numbers.sequence(from,to,step)}
<!-- html (Thymeleaf) --> 
<th:block th:each="num : ${#numbers.sequence(1,5)}">
	<div th:text="${num}"></div>
</th:block>
▼▼▼▼▼ 결과(HTML)
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>


반복 상태 변수 (status)


Thymeleaf에서  th:each 사용하면 반복 상태를 추적할 수 있는 status 변수를 제공해 주는데 이를 이용하여 index, count 등의 값을 쉽게 추출 할 수 있습니다.

index	현재 반복 인덱스  (0부터 시작)		
count	현재 반복 인덱스  (1부터 시작)	
size	총 요소 수
current	현재 요소
even	현재 반복이 짝수인지 여부 (boolean) 
odd	현재 반복이 홀수인지 여부 (boolean)
first	현재 반복이 첫번째인지 여부 (boolean) 
last	현재 반복이 마지막인지 여부 (boolean)
status 변수는 기본적으로 반복대상 오브젝트명 + "Stat" 변수명으로 접근 할 수 있으며 th:each 선언시 개발자가 직접 명명하여 사용 할 수도 있습니다.

<!--/* <div th:each="num, numStat : ${#numbers.sequence(1,3)}"> */ -->
<div th:each="num : ${#numbers.sequence(1,3)}">
	<p th:text="${'index : ' + numStat.index}"></p>
	<p th:text="${'count : ' + numStat.count}"></p>
	<p th:text="${'size : ' + numStat.size}"></p>
	<p th:text="${'current : ' + numStat.current}"></p>
	<p th:text="${'even : ' + numStat.even}"></p>
	<p th:text="${'odd : ' + numStat.odd}"></p>
	<p th:text="${'first : ' + numStat.first}"></p>
	<p th:text="${'last : ' + numStat.last}"></p>
</div>

▼▼▼▼▼ 상태 변수 결과(HTML)


<div>
	<p>index : 0</p>
	<p>count : 1</p>
	<p>size : 3</p>
	<p>current : 1</p>
	<p>even : true</p>
	<p>odd : false</p>
	<p>first : true</p>
	<p>last : false</p>
</div>
<div>
	<p>index : 1</p>
	<p>count : 2</p>
	<p>size : 3</p>
	<p>current : 2</p>
	<p>even : false</p>
	<p>odd : true</p>
	<p>first : false</p>
	<p>last : false</p>
</div>
<div>
	<p>index : 2</p>
	<p>count : 3</p>
	<p>size : 3</p>
	<p>current : 3</p>
	<p>even : true</p>
	<p>odd : false</p>
	<p>first : false</p>
	<p>last : true</p>
</div>


Reference

https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#using-theach