Thymeleaf

문지원(JiwonMoon)·2022년 1월 22일
0
post-thumbnail

Thymeleaf란?

타임리프는 뷰 템플릿 엔진으로 JSP, Freemarker와 같이 백엔드 쪽에서 클라이언트에게 응답할 브라우저 화면을 만들어 주는 역할은 한다 하지만 타임리프는 기존의 템플릿 엔진과 아래와 같은 차별점이 있다

• 서버상에서 동작하지 않아도 된다
• 순수 HTML구조를 유지한다

이게 중요한 이유는 기존의 템플릿으로는 항상 서버를 구동시켜 결과물을 확인해야 하지만 타임리프의 경우 static 파일을 사용하듯 해당 내용을 브라우저에서 바로 확인할 수 있다는 장점이 있다, 이것이 가능한 이유는 타임리프가 HTML의 속성(Attribute)을 기반으로 작성되기 때문에 기존의 HTML구조를 건드리지 않기 때문이다.

Natural Template (내추럴 템플릿)

서버를 구동하지 않으면 순수 HTML을, 서버를 구동하면 동적으로 HTML이 생성된다.
이렇게 타임리프는 순수 HTML을 유지하기 때문에 내추럴 템플릿으로도 불린다
타임리프는 th:xxx와 같이 값을 치환해주는 방식을 사용하기 때문에 내추럴 템플릿이 가능하다.

Thymeleaf with Spring

Spring에서도 공식적으로 Thymeleaf 사용을 권장하고 있기 때문에 타임리프를 통하여 스프링 프레임워크의 다양한 기능을 편리하게 사용할 수 있도록 지원한다.

핵심정리

타임리프는 기존 템플릿 엔진과 다르게 순수 HTML을 유지하는 내추럴 템플릿으로서, 서버를 구동하지 않고 직접 파일을 열어도 내용을 확인할 수 있고 서버를 통해 뷰 템플릿을 거치면 동적으로 HTML을 생성한다.
또한 스프링 프레임워크의 다양한 기능을 편리하게 사용할 수 있도록 지원하기 때문에 스프링과 함께 사용하기 편리하다.

사용법

아래의 사용법은 공식문서를 참고하여 작성했습니다.

<html xmlns:th="http://www.thymeleaf.org">

공식문서에서는 IDE 자동완성의 위함과 사용을 권장합니다.

문법 (Syntax)

1) ${...} 표현식

${...} 표현식을 이용해 컨트롤러에서 전달받은 변수에 접근할 수 있으며 th:속성명 내에서만 사용할 수 있습니다.

2) @{...} 표현식

@{...} 표현식은 서버의 contextPath를 의미하며 @{/} 는 "/contextPath/" 를 의미합니다.

3) 문자 합치기

합치고 싶은 문자열을 "|" 으로 감싸거나 + 연산자를 이용해 문자를 합칠 수 있습니다.

<div th:text="|My name is ${info.name} !! |"></div>
<div th:text="'My name is '+ ${info.name} + ' !! '"></div>

Message
home.properties home.welcome=Hello, {0}!
th:utext="#{home.welcome(${session.user.name})}

변수 (variable)

기본적인 객체 (basic objects)

유틸리티 객체 (utility objects)

  • #numbers
    sequence(from, to) : [from, to] 배열 생성, [from, to) 가 아님
  • #temporals (org.thymeleaf.extras.java8time.expression)
    format(target, pattern) : 날짜, 시간 포매팅

선택 (Selection)
th:object="${...}" 에 담긴 오브젝트의 필드를 *{...} 로 사용할 수 있음

<div th:object="${session.user}">
    <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
    <p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
    <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
</div>

Link URL

<!-- /order/details?orderId=3 -->
<a th:href="@{/order/details(orderId=${o.id})}"></a>

<!-- /order/3/details -->
<a th:href="@{/order/{orderId}/details(orderId=${o.id})}"></a>

request parameter는 ,(Comma)로 구분
/ 로 시작하는 URL은 자동으로 접두사로 application context name 붙음
If cookies are not enabled or this is not yet known, a ";jsessionid=..." suffix might be added to relative URLs so that the session is preserved. This is called URL Rewriting and Thymeleaf allows you to plug in your own rewriting filters by using the response.encodeURL(...) mechanism from the Servlet API for every URL. (이해 못함)

Fragments

<div th:insert="~{commons :: main}">...</div>

리터럴 (Literals)

  • Text literals
    • '(Single quote) 로 묶인 문자열. '를 사용하려면 \'로 사용
      • 로 문자열을 더할 수 있음 'My name is ' + ${user.name}
  • Number
  • Boolean (true false)
  th:if="${user.isAdmin()} == false"
  • null

Literal substitutions
| 로 묶인 문자열
안에는 ${...} *{...} #{...} 외의 표현식은 사용할 수 없음
'...' text literals 도 사용할 수 없음

Elvis operator

Age: 27.

... ?: ... 첫 번째 표현식이 null일 경우 두 번째 값 사용 두 번째 값으로 _ 를 사용하면 null일 경우 아무 것도 하지 않음

기타

  • Arithmetic operations
      • div/ mod%
  • Comparators and Equality
    gt> lt< ge>= le<= eq== ne!= not!
  • Conditional expressions
    ? ... : ... 삼항 연산자, : 가 없을 경우 false일 때 null 반환

속성 (attribute)

초기 값 (setting value)

th:attr : 속성의 값 설정. ,로 구분

<img src="../../images/gtvglogo.png" 
     th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />

<!-- 렌더링 후 -->
<img src="/gtgv/images/gtvglogo.png" title="Logo de Good Thymes" alt="Logo de Good Thymes" />
  • 특정 속성의 값 설정: th:src ... 목록
  • 둘 이상의 속성 한번에 설정 th:title-alt 등

appending and prepending

  • th:attrappend suffix추가
  • th:attrprepend prefix 추가
    th:classappend th:styleappend ...

Fixed-value boolean attributes
표현식이 true 일 경우 속성 추가

th:checked

기타
th:text : 태그 안의 텍스트
th:utext : Unescaped test (<b> -> )

반복문 (Iteration)

  <tr th:each="prod : ${prods}">
    <td th:text="${prod.name}">Onions</td>
    <td th:text="${prod.price}">2.41</td>
    <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>

반복문의 값(Iterable values)

  • java.util.Iterable
  • java.util.Enumeration
  • java.util.Iterator
  • java.util.Map 반복할 때 Entry 사용
  • Any Array

th:each

each문을 이용해 반복문을 표현합니다.

<th:block th:each="data:${datas}">
	<h1 th:text="${data}"></h1>
</th:block>

status 변수

th:each="prod,iterStat : ${prods}"
  • index : 0부터 시작하는 index
  • count : 1부터 시작하는 index
  • size : 총 개수
  • current : 현재 index의 변수
  • even odd : 짝수/홀수 여부
  • first last : 처음/마지막 여부
<th:block th:each="data,status:${datas}">
	<h1 th:text="|${status.count} ${data}|"></h1>
</th:block>

Conditional Evaluation

  • th:if
  • th:unless (th:if="${not ...}")

true value

null is false

switch 문(switch case)

th:switch th:case
th:case="*" == default
<th:block th:switch="${info.name}">
<div th:case="lee"> 당신은 이씨 입니다.</div>
<div th:case="kim"> 당신은 김씨 입니다.</div>
</th:block>

Template Layout

  • 선언
    • th:fragment
  • 사용
    • th:insert : 태그 안에 fragment 삽입
    • th:replace : 태그를 fragment로 교체

주석 (Comments and Blocks)

  <!-- 일반 주석 -->
<!-- /* 처리 후 사라지는 주석 */-->

<!--/*--> 
  <div>
     처리 전에만 볼 수 있음
  </div>
<!--*/-->

<!--/*/
  <div th:text="${...}">
    처리 중에는 태그로 인식, 그냥 볼 경우 주석
  </div>
/*/-->
<table>
  <th:block th:each="user : ${users}">
    <tr>
        <td th:text="${user.login}">...</td>
        <td th:text="${user.name}">...</td>
    </tr>
    <tr>
        <td colspan="2" th:text="${user.address}">...</td>
    </tr>
  </th:block>
</table>

tip: th:block 간단한 컨테이너. 파싱 후 안의 컨텐츠만 남기고 사라짐

인라이닝 (Inlining)

<p>Hello, [[${session.user.name}]]!</p>
<p>Hello, <span th:text="${session.user.name}">Sebastian</span>!</p>

[[...]] inline expressions
[(...)] unescape inline expressions (th:utext)
th:inline="none" : inlining 비활성화

자바스크립트 인라이닝(Javascript inline)
th:inline="javascript"

<script th:inline="javascript">
  	var username = [[${session.user.name}]];
  	var username = "Sebastian \"Fruity\" Applejuice";
  
  	var username = [(${session.user.name})];
  	var username = Sebastian "Fruity" Applejuice; // 주의
  
  	var username = /*[[${session.user.name}]]*/ "Gertrud Kiwifruit";
  	// 처리 후 블록 주석 뒤의 내용은 없어짐
  	
  	/*<![CDATA[*/
	var URL = "[(@{/board/{id}(id=${post.id})})]"
	/*]]>*/
  	
</script>

References (참고 자료)

0개의 댓글