1. 서버 사이드 HTML 렌더링(SSR)
타임리프는 백엔드 서버에서 HTML을 동적으로 렌더링하는 용도로 사용된다.
2. 네츄럴 템플릿
타임리프는 순수 HTML을 최대한 유지하는 특징이 있다.
타임리프로 작성한 파일은 HTML을 유지해서 웹브라우저에서 파일을 직접 열어도 내용을 확인할 수 있고, 서버를 통해 뷰 템플릿을 거치면 동적으로 변경된 결과를 확인할 수 있다.
즉, 순수 HTML을 유지하면서 뷰 템플릿도 사용할 수 있는 타임리프의 특징을 네츄럴 템플릿이라 한다.
3. 스프링 통합 지원
타임리프는 스프링과 자연스럽게 통합되고, 스프링의 다양한 기능을 편리하게 사용할 수 있게 지원한다.
타임리프를 사용하려면 다음과 같은 선언을 해야 한다.
<html xmlns:th="http://www.thymeleaf.org">
간단한 표현식
${...}
*{...}
#{...}
@{...}
~{...}
리터럴
문자연산
산술 연산
불린 연산
비교와 동등
조건 연산
특별한 토큰
타임리프에서 텍스트를 출력하는 방법은 2가지 있다.
1. HTML 태그의 속성에 기능을 정의해서 사용.
HTML의 콘텐츠(content)에 데이터를 출력할 때는 th:text
를 사용한다.
<span th:text="${data}">
[[...]]
를 사용한다.[[${data}]]
웹브라우저는 <를 HTML태그의 시작으로 인식하는데, <를 태그의 시작이 아니라 문자로 표현하는 방법을 HTML 엔티티라고 한다. 그리고 이처럼 HTML에서 사용하는 특수문자를 HTML 엔티티로 변경하는 것을 이스케이프(escape)라고 한다.
그리고 타임리프가 제공하는 th:text
,[[...]]
는 기본적으로 이스케이프(escape)를 제공한다.
<
-> <
>
-> >
이러한 이스케이프 기능을 사용하지 않기 위한 방법은 아래와 같다.
th:text
-> th:utext
[[...]]
-> [{...}]
사용 예시
<span th:utext="${data}"></span>
<li><span th:inline="none">[[...]] = </span>[[${data}]]</li>
th:inline="none"
: 타임리프는 <span>
태그 사이의 [[...]]
를 해석하기 때문에, 화면에 [[...]]
라는 글자자체를 보여줄 수 없다.
이 태그 안에서는 타임리프가 해석하지 말라는 옵션이다.
타임리프에서는 변수를 사용할때 변수 표현식을 사용한다.
변수 표현식 : ${...}
그리고 이 변수 표현식에는 스프링EL이라는 스프링이 제공하는 표현식을 사용할 수 있다.
객체 User user
-> 클래스 변수 String username
, int age
user.username
: 프로퍼티 접근 -> user.getUsername()
user['username']
: 프로퍼티 접근 -> user.getUsername()
user.getUsername()
: user의 getUsername()
을 직접 호출리스트 List<User> list
model.addAttribute("users", list);
users[0].username
: List에서 첫번째 user를 찾고 username 프로퍼티 접근 -> list.get(0).getUsername()
users[0]['username']
: 위와 같이 username 프로퍼티 접근 -> list.get(0).getUsername()
users[0].getUsername()
: List에서 첫번째 user를 찾고 메서드 직접 호출맵 Map<String, User> map
model.addAttribute("userMap", map);
userMap['userA'].username
: Map에서 userA를 찾고, username 프로퍼티 접근 -> map.get("userA").getUsername()
userMap['userA']['username']
: 위와 같이 username 프로퍼티 접근 -> map.get("userA").getUsername()
userMap['userA'].getUsername()
: Map에서 userA를 찾고 메서드 직접 호출th:with
사용하여 지역 변수 선언이 가능하다.
지역 변수는 선언한 태그 안에서만 사용할 수 있다.
사용 예시는 아래와 같다.
<h1>지역 변수 - (th:with)</h1>
<div th:with="first=${users[0]}">
<p>처음 사람의 이름은 <span th:text="${first.username}"></span></p>
</div>
타임리프는 기본 객체들을 제공한다.
${#request}
${#response}
${#session}
${#servletContext}
${#locale}
이때 ${#request}
는 HttpServletRequest객체가 그대로 제공되어서 데이터를 조회하려면 request.getParameter("data")
처럼 불편하게 접근해야 한다. 이런 불편함을 해결하기 위한 편의 객체도 제공한다.
param
${param.paramData}
request.getParameter("data")
대신 위와 같이 쓸 수 있다.http://localhost:8080/basic/basic-object?paramData=HelloParam
public String basicObjects(@RequestParam String paramData, Model model) {
model.addAttribute("paramData", paramData);
return "basic/basic-objects";
}
위처럼 해준다음 타임리프에서 사용했어야 했지만,
타임리프에서 바로 <span th:text="${param.paramData}"></span>
로 사용가능하다.
HTTP 세션 접근: session
예) ${session.sessionData}
스프링 빈 접근: @
예) ${@helloBean.hello('Spring!')}
타임리프는 문자, 숫자, 날짜, URL등을 편리하게 다루는 다양한 유틸리티 객체들을 제공한다.
참고 사이트
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#expression-utilityobjects
타임리프에서 URL을 생성할 때는 @{...}
문법을 사용하면 된다.
단순한 URL
@{/hello}
-> /hello
쿼리 파라미터
@{/hello(param1=${param1},param2=${param2})}
-> /hello?param1=data1¶m2=data2
()
에 있는 부분은 쿼리 파라미터로 처리된다.경로 변수
@{hello/{param1}{param1=${param1}, param2=${param2}}}
-> /hello/data?param2=data2
상대경로, 절대경로, 프로토코로 기준으로 표현할 수 있다.
/hello
: 절대 경로
hello
: 상대 경로
리터럴은 소스 코드상에 고정된 값을 말하는 용어이다.
타임리프에서 문자 리터럴은 항상 '
(작은 따옴표)로 감싸야 한다. 하지만 공백 없이 쭉 이어진다면 하나의 의미있는 토큰으로 인지해서 다음과 같이 작은 따옴표를 생략할 수 있다.
룰: A-Z
, a-z
, 0-9
, []
, .
, -
, _
예시:
'
생략 x: <span th:text="'hello'">
'
생략 o: <span th:text="hello">
사용 예시:
<span th:text="'hello' + ' world!'"></span>
<span th:text="'hello world!'"></span>
<span th:text="'hello ' + ${data}"></span>
<span th:text="|hello ${data}|"></span>
<span th:text="|hello ${data}|">
이처럼 리터럴 대체 문법(|...|
)을 사용하면 공백이 있어도, ${data}
와 같이 값을 가져와야 할때도 따로 연산을 하지 않고 한번에 편리하게 쓸 수 있다.
타임리프 연산은 자바와 크게 다르지 않다. HTML안에서 사용해서 HTML엔티티를 사용하는 부분만 주의하면 된다.
산술 연산
예시)
<span th:text="10 + 2"></span>
<span th:text="10 % 2 == 0"></span>
비교 연산
>
(gt), <
(lt), >=
(ge), <=
(le), !
(not), ==
(eq), !=
(neq, ne)<span th:text="1 > 10"></span>
<span th:text="1 gt 10"></span>
<span th:text="1 >= 10"></span>
조건식
자바의 조건식과 유사하다.
예시)
<span th:text="(10 % 2 == 0)? '짝수':'홀수'"></span>
Elvis 연산자
조건식의 편의 버전
<span th:text="${data}?: '데이터가 없습니다.'"></span>
<span th:text="${nullData}?: '데이터가 없습니다.'"></span>
No-Operation
_
인 경우 마치 타임리프가 실행되지 않는 것처럼 동작한다. 이것을 잘 사용하면 HTML의 내용 그대로 활용할 수 있다. 밑의 예를 보면 '데이터가 없습니다.' 부분이 그대로 출력된다.
예시)
<span th:text="${data}?: _">데이터가 없습니다.</span>
<span th:text="${nullData}?: _">데이터가 없습니다.</span>