타임리프는 백엔드에서 HTML을 동적으로 렌더링하는 용도로 사용된다.
서버사이드렌더링(SSR)할 때 사용된다.
타임리프의 가장 큰 특징은 내츄럴 템플릿이라는 것이다.
내츄럴 템플릿이란 순수 HTML을 유지한다는 것인데 유지하기때문에 웹 브라우저에서 타임리프로 작성한 html 파일을 열어서 내용을 확인할 수 있지만 동적으로 변경된 결과는 아닐지라도 HTML 구조와 같은 부분은 볼 수 있다는 뜻이다.
그리고 서버와 뷰 템플릿을 통해 타임리프 파일이 열리면 동적으로 변경된 결과를 확인할 수 있다.
타임리프를 사용할 때는 다음과 같은 선언을 해야한다.
<html xmlns:th="http://www.thymeleaf.org">
타임리프에서 텍스트를 출력하고 싶을 때는 다음과 같이 th:text를 사용하면된다.
@GetMapping("/text-basic")
public String textBasic(Model model){
model.addAttribute("data", "Hello Spring!");
return "basic/text-basic";
}
<span th:text="${data}"></span>
뷰 템플릿을 통해 화면에 출력될 때는 다음과 같이 렌더링이 된다.
<span>Hello Spring!</span>
만약 태그안에 작성하지 않고 컨텐츠 부분에 바로 작성하고 싶으면 다음과 같이 작성하면된다.
<span>[[${data}]]</span>
이러면 위 결과와 동일하게 나온다.
참고로 타임리프는 [[ ]]와 같은 특수문자를 HTTP 엔티티로 이스케이프를 해준다.
만약 이스케이프 기능을 사용하고 싶지 않으면 th:utext를 사용하면된다.
@GetMapping("/text-unescaped")
public String upescapedBasic(Model model){
model.addAttribute("data", "Hello <b>Spring!</b>");
return "basic/text-unescaped";
}
<span th:utext="${data}"></span>
렌더링 결과 Spring!은 굵은 글자로 표현.
<span>Hello <b>Spring!</b></span>
만약 th:text였으면 아래와 같이 표현되었을 것이다.
<span>Hello <b>Spring!</b></b></span>
만약 콘텐츠 영역에 바로 작성하고싶으면 다음과 같이 작성하면된다.
th:text가 [[]]였다면 th:utext는[()]로 사용한다.
<span>[(${data})]</span>
타임리프에서 변수를 사용하고 싶으면 다음과 같은 변수 표현식을 사용하면 된다.
${...}
@GetMapping("/text-basic")
public String textBasic(Model model){
model.addAttribute("data", "Hello Spring!");
return "basic/text-basic";
}
<span th:text="${data}"></span>
data = Hello Spring!이 담겨있는 것이고, 변수인 data를 가져오고싶으면 &{data}로 가져올 수 있다.
만약 user객체가 있고 username이라는 프로퍼티가 있다고 가정하자.
다음과 같이 Object, list, Map타입이 들어가있을때는 어떻게 값을 꺼내는지 알아보자.
@GetMapping("/variable")
public String variable(Model model){
User userA = new User("UserA", 10);
User userB = new User("UserB", 20);
ArrayList<User> list = new ArrayList<>();
list.add(userA);
list.add(userB);
Map<String, User> map = new HashMap<>();
map.put("UserA", userA);
map.put("UserB", userB);
model.addAttribute("user", userA);
model.addAttribute("users", list);
model.addAttribute("userMap", map);
return "basic/variable";
}
Object
<span th:text="${user.username}"></span>
<span th:text="${user['username']}"></span>
list
<span th:text="${users[0].username}"></span>
<span th:text="${users[0]['username']}"></span>
<span th:text="${users[0].getUsername()}"></span>
Map
<span th:text="${userMap['userA'].username}"></span>
<span th:text="${userMap['userA']['username']}"></span>
<span th:text="${userMap['userA'].getUsername()}"></span>
지역변수 같은 경우는 th:with를 사용할 수 있다.
<div th:with="first=${users[0]}">
<span th:text="${first.username}"></span>
</div>
타임리프는 다음과 같은 객체들을 기본으로 제공해준다
<span th:text="${#request}"></span>
<span th:text="${#response}"></span>
<span th:text="${#session}"></span><
<span th:text="${#servletContext}"></span>
<span th:text="${#locale}"></span>
Bean으로 등록된 객체에 접근할 수도 있다.
@Component("helloBean")
static class HelloBean {
public String hello(String data){
return "Hello " + data;
}
}
<span th:text="${@helloBean.hello('Spring')}"></span>
타임리프는 자주 사용하는 것들에 대해서는 편의 객체를 제공해주는데 대표적으로 request parameter와 session이 있다.
request parameter
<span th:text="${param.paramData}"></span>
session
<span th:text="${session.sessionData}"></span>
타임리프에서 URL을 생성할 때에는 $표시가 아닌 @를 사용해야한다
@{...}
다음과 같이 모델에 데이터를 넘긴다고 가정하자.
model.addAttribute("param1", "data1");
model.addAttribute("param2", "data2");
링크 예시
<a th:href="@{/hello}"></a>
<a th:href="@{/hello(param1=${param1}, parma2=${param2})}"></a>
<a th:href="@{/hello/{param1}/{param2}(param1=${param1}, param2=${param2})}"></a>
<a th:href="@{/hello/{param1}(param1=${param1}, param2=${param2})}"></a>
실행 결과 다음과 같은 링크가 생성된다. (순서대로)
/hello
/hello?param1=data1&parma2=data2 -> query parameter 방식
/hello/data1/data2 -> Path variable 방식
/hello/data1?param2=data2 -> query parameter + Path variable