타임리프(Thymeleaf)는 현재 스프링부트에서 밀고 있는 프레임워크이다. JSP는 자바소스(.java)에서 바이트코드(.class)로 변환하는 과정을 거친다. 그러나 타임리프는 그런 과정 없이 순수한 html에 태그를 추가하여 html을 조작한다.
아래는 HTML 파일이다.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"> ........... (1)
<head>
<meta charset="UTF-8">
<title>$Title$</title>
<style>
table{
border: 1px black solid;
}
td{
border: 1px black solid;
}
</style>
</head>
<body>
<table>
<tr>
<td>id</td>
<td>pw</td>
<td>name</td>
<td>regDate</td>
</tr>
<tr th:each="dto : ${result.dtoList}"> ........(2)
<td>[[${dto.id}]]</td>.........(3)
<td>[[${dto.pw}]]</td>
<td>[[${dto.name}]]</td>
<td>[[${#temporals.format(dto.regDate,'yyyy/MM/dd')}]]</td> ........(4)
</tr>
</table>
</body>
</html>
(1) 타임리프를 로딩한다. th는 타임리프 기능을 호출할 때 사용한다.
(2) HTML로서 그 형태를 완벽하게 유지한 상태에서 타임리프의 기능을 사용할 수 있다. 해당 for 반복문은 향상된 for문과 그 형태가 유사하다. 참고로 앞의 result는 Model을 통해 전달된 객체이다. for문이 끝나는 곳을 명시할 필요가 없이, 해당 태그 블럭 안에서 작동한다.
(3) 태그 안에서 데이터를 호출하는 것과 태그 밖에서 호출하는 방식이 다르다. 태그에서는 {}]]을 사용한다.
(4) 타임리프는 다양한 매서드를 제공하며, 매서드를 호출할 때는 #을 사용한다. 참고로 regDate는 LocalDateTime 데이타이다.
타임리프에서 redirect를 하는 방법은 아래와 같다.
<a th:href="@{/member/modify(id=${dto.id})}"><input type="button" value="modify"></a>
th:href | redirect를 위한 태그 |
@{/.....} | @을 식별자로 하여 url을 작성 |
(id=${dto.id}) | GET으로의 param을 적용할 때, ?을 사용하지 않고, 소괄호를 사용 |
<ul>
<li th:if="${result.prev}">.......(1)
<a th:href="@{/member/list(page=${result.start-1})}">prev</a>
</li>
<li th:each="page: ${result.pageList}">
<a th:href="@{/member/list(page=${page})}" th:class="${result.page==page?'bold':''}">[[${page}]]</a>......(2)
</li>
<li th:if="${result.next}">
<a th:href="@{/member/list(page=${result.end+1})}">next</a>
</li>
</ul>
(1) if문을 사용하기 위한 태그이다. 참고로 prev의 경우 boolean을 데이타타입으로 한다. 그 값이 true면 해당 li태그가 존재하며, 그렇지 않으면 야예 생략된다.
(2) (1)과 달리 태그 자체는 남는다. 태그의 속성 중 하나인 class의 값을 if문을 통해 부여한다. 향상된 if문을 사용한다.
타임리프에서 input을 다루는 방법은 아래와 같다. 참고로 검색기능을 만들 때 아래와 같이 작성한다. 제이쿼리를 사용했다.
<form action="/member/list" method="get" id="searchForm">
<input type="hidden" name="page" value="1">
<input type="text" name="keyword" placeholder="검색어입력" th:value="${pageRequestDTO.keyword}"> ............ (1)
<select name="type">
<option value="" th:selected="${pageRequestDTO.type==null}">-----</option> ........... (2)
<option value="p" th:selected="${pageRequestDTO.type=='p'}">pw</option>
<option value="n" th:selected="${pageRequestDTO.type=='n'}">name</option>
<option value="pn" th:selected="${pageRequestDTO.type=='pn'}">pw+name</option>
</select>
<input type="button" class="btn-search" value="search">
<input type="button" class="btn-clear" value="clear">
</form>
<script th:inline="javascript"> ...........(3)
var searchForm = $("#searchForm");
$('.btn-search').on('click', function (){
searchForm.submit();
});
$('.btn-clear').on('click', function (){
searchForm.empty().submit();
});
</script>
(1) th:value를 통해 그 값을 전달 받는다.
(2) th:selected는 true / false를 통해 selected 속성을 추가할지 하지 않을지를 결정한다. 원래의 jsp는 for와 if를 통해 원하는 객체만을 out.print("....selected...") 를 추가한다. 훨씬 손쉬운 방법으로 가능하다.
(3) script를 선언할 수 있으며 이 경우 th:inline 태그를 사용한다.