Thymeleaf 기본기능 사용법

Bobby·2021년 7월 3일
2

또 까먹었지..?

목록 보기
2/4
post-thumbnail

1. 텍스트 - text, utext

구분textutext
escape사용사용하지 않음
태그의 속성으로 값 출력th:textth:utext
직접 데이터 출력[[...]][(...)]

사용 예

<h1>text vs utext</h1>
<ul>
    <li>th:text = <span th:text="${data}"></span></li>
    <li>th:utext = <span th:utext="${data}"></span></li>
</ul>
<h1><span th:inline="none">[[...]] vs [(...)]</span></h1>
<ul>
    <li><span th:inline="none">[[...]] = </span>[[${data}]]</li>
    <li><span th:inline="none">[(...)] = </span>[(${data})]</li>
</ul>

출력


2. 변수 - SpringEL

  • 변수 사용시 변수 표현식 사용 : ${...}

다양한 변수 접근 방법

  • ex) User 클래스
public class User {
    private String username;
    private int age;

    public User(String username, int age) {
        this.username = username;
        this.age = age;
    }
}
ObjectListMap
${user.username}${users[0].username}${userMap['userA'].username}
${user['username']}${users[0]['username']}${userMap['userA']['username']}
${user.getUsername()}${users[0].getUsername()}${userMap['userA'].getUsername()}

지역변수 사용
1. th:with 태그 이용
2. 지역변수는 선언한 태그에서만 사용 가능

사용 예

<h1>SpringEL 표현식</h1>
<ul>Object
    <li>${user.username} = <span th:text="${user.username}"></span></li>
    <li>${user['username']} = <span th:text="${user['username']}"></span></li>
    <li>${user.getUsername()} = <span th:text="${user.getUsername()}"></span></li>
</ul>
<ul>List
    <li>${users[0].username} = <span th:text="${users[0].username}"></span>
    </li>
    <li>${users[0]['username']} = <span th:text="${users[0]['username']}"></span>
    </li>
    <li>${users[0].getUsername()} = <span th:text="${users[0].getUsername()}"></span></li>
</ul>
<ul>Map
    <li>${userMap['userA'].username} = <span th:text="${userMap['userA'].username}"></span></li>
    <li>${userMap['userA']['username']} = <span th:text="${userMap['userA']['username']}"></span></li>
    <li>${userMap['userA'].getUsername()} = <span th:text="${userMap['userA'].getUsername()}"></span></li>
</ul>

<h1>지역 변수 - (th:with)</h1>
<div th:with="first=${users[0]}">
    <p>처음 사람의 이름은 <span th:text="${first.username}"></span></p>
</div>

출력


3. thymeleaf 기본객체들

ex) 스프링 빈 등록

@Component("helloBean")
public class HelloBean {
    public String hello(String data) {
        return "Hello" + data;
    }
}
객체설명
${#request}HttpRequest 객체 접근
${#response}HttpResponse 객체 접근
${#session}HttpSession 객체 접근
${#servletContext}ServletContext 객체 접근
${#locale}Locale 객체 접근
${param.paramData}request.getParameter()
${session.sessionData}세션 값 바로 사용
${@helloBean.hello('Spring!')}Spring Bean에 바로 접근

사용 예

<h1>식 기본 객체 (Expression Basic Objects)</h1>
<ul>
    <li>request = <span th:text="${#request}"></span></li>
    <li>response = <span th:text="${#response}"></span></li>
    <li>session = <span th:text="${#session}"></span></li>
    <li>servletContext = <span th:text="${#servletContext}"></span></li>
    <li>locale = <span th:text="${#locale}"></span></li>

</ul>
<h1>편의 객체</h1>
<ul>
    <li>Request Parameter = <span th:text="${param.paramData}"></span></li>
    <li>session = <span th:text="${session.sessionData}"></span></li>
    <li>spring bean = <span th:text="${@helloBean.hello('Spring!')}"></span></li>
</ul>

출력


4. 유틸리티 객체와 날짜

객체설명
#message메시지, 국제화 처리
#urisURI 이스케이프 지원
#datesjava.util.Date 서식 지원 #calendars : java.util.Calendar 서식 지원
#temporals자바8 날짜 서식 지원
#numbers숫자 서식 지원
#strings문자 관련 편의 기능
#objects객체 관련 기능 제공
#boolsboolean 관련 기능 제공
#arrays배열 관련 기능 제공
#lists , #sets , #maps컬렉션 관련 기능 제공
#ids아이디 처리 관련 기능 제공, 뒤에서 설명

사용법

https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#appendix-b-expression-utility-objects

자바8 날짜

  • 타임리프에서 LocalDateTime, LocalDate, Instance를 사용할 수 있다.
  • 라이브러리 추가 필요 (spring boot starter thymeleaf 사용 시 자동 추가)
	thymeleaf-extras-java8time
  • #temporals 로 사용할 수 있다.

사용 예

  • ${localDateTime} 의 경우 Model에 담겨 넘어온 값
<ul>
    <li>default = <span th:text="${localDateTime}"></span></li>
    <li>yyyy-MM-dd HH:mm:ss = <span th:text="${#temporals.format(localDateTime,'yyyy-MM-dd HH:mm:ss')}"></span></li>
</ul>
<h1>LocalDateTime - Utils</h1>
<ul>
    <li>${#temporals.day(localDateTime)} = <span th:text="${#temporals.day(localDateTime)}"></span></li>
    <li>${#temporals.month(localDateTime)} = <span th:text="${#temporals.month(localDateTime)}"></span></li>
    <li>${#temporals.monthName(localDateTime)} = <span th:text="${#temporals.monthName(localDateTime)}"></span></li>
    <li>${#temporals.monthNameShort(localDateTime)} = <span th:text="${#temporals.monthNameShort(localDateTime)}"></span></li>
    <li>${#temporals.year(localDateTime)} = <span th:text="${#temporals.year(localDateTime)}"></span></li>
    <li>${#temporals.dayOfWeek(localDateTime)} = <span th:text="${#temporals.dayOfWeek(localDateTime)}"></span></li>
    <li>${#temporals.dayOfWeekName(localDateTime)} = <span th:text="${#temporals.dayOfWeekName(localDateTime)}"></span></li>
    <li>${#temporals.dayOfWeekNameShort(localDateTime)} = <span th:text="${#temporals.dayOfWeekNameShort(localDateTime)}"></span></li>
    <li>${#temporals.hour(localDateTime)} = <span th:text="${#temporals.hour(localDateTime)}"></span></li>
    <li>${#temporals.minute(localDateTime)} = <span th:text="${#temporals.minute(localDateTime)}"></span></li>
    <li>${#temporals.second(localDateTime)} = <span th:text="${#temporals.second(localDateTime)}"></span></li>
    <li>${#temporals.nanosecond(localDateTime)} = <span th:text="${#temporals.nanosecond(localDateTime)}"></span></li>
</ul>

출력


5. URL 링크

-Model객체에 데이터 저장

public String link(Model model) {
    model.addAttribute("param1", "data1");
    model.addAttribute("param2", "data2");

    return "basic/link";
}
URL 유형설명
단순한 URL@{/hello} -> /hello
쿼리 파라미터@{/hello(param1=param1,param2={param1}, param2={param2})}
-> /hello?param1=data1&param2=data2
-> () 에 있는 부분은 쿼리 파라미터로 처리된다.
경로 변수@{/hello/{param1}/{param2}(param1=param1,param2={param1}, param2={param2})}
-> /hello/data1/data2
-> URL 경로상에 변수가 있으면 () 부분은 경로 변수로 처리된다.
경로 변수 + 쿼리 파라미터@{/hello/{param1}(param1=param1,param2={param1}, param2={param2})}
-> /hello/data1?param2=data2
-> 경로 변수와 쿼리 파라미터를 함께 사용할 수 있다.
  • 상대경로, 절대경로 표현
  • /hello : 절대 경로
  • hello : 상대 경로

사용 예

<h1>URL 링크</h1>
<ul>
  <li><a th:href="@{/hello}">basic url</a></li>
  <li><a th:href="@{/hello(param1=${param1}, param2=${param2})}">hello query param</a></li>
  <li><a th:href="@{/hello/{param1}/{param2}(param1=${param1}, param2=${param2})}">path variable</a></li>
  <li><a th:href="@{/hello/{param1}(param1=${param1}, param2=${param2})}">path variable + query parameter</a></li>
</ul>

출력


6. 리터럴

  • 리터럴은 소스 코드상에 고정된 값을 말하는 용어이다.
  • 타임리프에서 문자 리터럴은 항상 ' (작은 따옴표)로 감싸야 한다.
리터럴사용
문자'hello'
숫자10
불린true , false
nullnull
  • 리터럴 대체(Literal substitutions)
    |...| 로 감싸 대체 할 수 있다.

사용 예

<ul>
  <li>'hello' + ' world!' = <span th:text="'hello' + ' world!'"></span></li> 
  <li>'hello world!' = <span th:text="'hello world!'"></span></li>
  <li>'hello ' + ${data} = <span th:text="'hello ' + ${data}"></span></li> 
  <li>리터럴 대체 |hello ${data}| = <span th:text="|hello ${data}|"></span></li>
</ul>

출력


7. 연산

연산사용
비교연산HTML 엔티티를 사용해야 하는 부분을 주의
> (gt), < (lt), >= (ge), <= (le), ! (not), == (eq), != (neq, ne)
조건식자바의 조건식과 유사하다.
Elvis 연산자조건식의 편의 버전
No-Operation_ 인 경우 마치 타임리프가 실행되지 않는 것 처럼 동작한다.
이것을 잘 사용하면 HTML 의 내용 그대로 활용할 수 있다.
마지막 예를 보면 데이터가 없습니다. 부분이 그대로 출력된다.

사용 예

<ul>
    <li>산술 연산
        <ul>
            <li>10 + 2 = <span th:text="10 + 2"></span></li>
            <li>10 % 2 == 0 = <span th:text="10 % 2 == 0"></span></li>
        </ul>
    </li>
    <li>비교 연산
        <ul>
            <li>1 > 10 = <span th:text="1 &gt; 10"></span></li>
            <li>1 gt 10 = <span th:text="1 gt 10"></span></li>
            <li>1 >= 10 = <span th:text="1 >= 10"></span></li>
            <li>1 ge 10 = <span th:text="1 ge 10"></span></li>
            <li>1 == 10 = <span th:text="1 == 10"></span></li>
            <li>1 != 10 = <span th:text="1 != 10"></span></li>
        </ul>

    </li>
    <li>조건식
        <ul>
            <li>(10 % 2 == 0)? '짝수':'홀수' = <span th:text="(10 % 2 == 0)? '짝수':'홀수'"></span></li>
        </ul>
    </li>
    <li>Elvis 연산자
        <ul>
            <li>${data}?: '데이터가 없습니다.' = <span th:text="${data}?: '데이터가 없습니다.'"></span></li>
            <li>${nullData}?: '데이터가 없습니다.' = <span th:text="${nullData}?: '데이터가 없습니다.'"></span></li>
        </ul>
    </li>
    <li>No-Operation
        <ul>
            <li>${data}?: _ = <span th:text="${data}?: _">데이터가 없습니다.</span></li>
            <li>${nullData}?: _ = <span th:text="${nullData}?: _">데이터가 없습니다.</span></li>
        </ul>
    </li>
</ul>

출력


8. 속성 값 설정

  • 타임리프 태그 속성(Attribute)
  • 타임리프는 주로 HTML 태그에 th: 속성을 지정하는 방식으로 동작한다. th: 로 속성을 적용하면 기존
    속성을 대체한다. 기존 속성이 없으면 새로 만든다.
속성 값 설정사용
속성 설정th: 속성을 지정하면 타임리프는 기존 속성을 th: 로 지정한 속성으로 대체한다.
기존 속성이 없다면 새로 만든다.
속성 추가th:attrappend : 속성 값의 값에 값을 추가한다.
th:attrprepend : 속성 값의 뒤에 값을 추가한다.
th:classappend : class 속성에 자연스럽게 추가한다.
checked 처리HTML에서 checked 속성은 checked 속성의 값과 상관없이 checked 라는 속성만 있어도 체크가 된다.
타임리프의 th:checked 는 값이 false 인 경우 checked 속성 자체를 제거한다.

사용 예

<h1>속성 설정</h1>
<input type="text" name="mock" th:name="userA"/>
<h1>속성 추가</h1>
- th:attrappend = <input type="text" class="text" th:attrappend="class=' large'"/><br/>
- th:attrprepend = <input type="text" class="text" th:attrprepend="class='large '"/><br/>
- th:classappend = <input type="text" class="text" th:classappend="large" /><br/>

<h1>checked 처리</h1>
- checked o <input type="checkbox" name="active" th:checked="true"/><br/>
- checked x <input type="checkbox" name="active" th:checked="false"/><br/>
- checked=false <input type="checkbox" name="active" checked="false"/><br/>

출력


9. 반복

  • 데이터 생성
...

List<User> list = new ArrayList<>();
list.add(new User("userA", 10));
list.add(new User("userB", 20));
list.add(new User("userC", 30));
model.addAttribute("users", list);

...
반복사용
반복 기능<tr th:each="user : ${users}">
반복시 오른쪽 컬렉션( ${users} )의 값을 하나씩 꺼내서 왼쪽 변수( user )에 담아서 태그를 반복
th:each 는 List 뿐만 아니라 배열, java.util.Iterable , java.util.Enumeration 을 구현한 모든 객체를 반복에 사용가능
Map 도 사용할 수 있는데 이 경우 변수에 담기는 값은 Map.Entry
반복 상태 유지<tr th:each="user, userStat : ${users}">
반복의 두번째 파라미터를 설정해서 반복의 상태를 확인 가능
두번째 파라미터는 생략 가능한데, 생략하면 지정한 변수명( user ) + Stat
반복 상태 유지 기능index : 0부터 시작하는 값
count : 1부터 시작하는 값
size : 전체 사이즈
even , odd : 홀수, 짝수 여부( boolean )
first , last :처음, 마지막 여부( boolean )
current : 현재 객체

사용 예

<h1>기본 테이블</h1>
<table border="1">
    <tr>
        <th>username</th>
        <th>age</th>
    </tr>
    <tr th:each="user : ${users}">
        <td th:text="${user.username}">username</td>
        <td th:text="${user.age}">0</td>
    </tr>
</table>
<h1>반복 상태 유지</h1>
<table border="1">
    <tr>
        <th>count</th>
        <th>username</th>
        <th>age</th>
        <th>etc</th>
    </tr>
    <tr th:each="user, userStat : ${users}">
        <td th:text="${userStat.count}">username</td>
        <td th:text="${user.username}">username</td>
        <td th:text="${user.age}">0</td>
        <td>
            index = <span th:text="${userStat.index}"></span>
            count = <span th:text="${userStat.count}"></span>
            size = <span th:text="${userStat.size}"></span>
            even? = <span th:text="${userStat.even}"></span>
            odd? = <span th:text="${userStat.odd}"></span>
            first? = <span th:text="${userStat.first}"></span>
            last? = <span th:text="${userStat.last}"></span>
            current = <span th:text="${userStat.current}"></span>
        </td>
    </tr>
</table>

출력


10. 조건부 평가

조건식사용
if, unlessif : 조건 만족 시 렌더링
unless : 조건이 만족하지 않을 시 렌더링
타임리프는 해당 조건이 맞지 않으면 태그 자체를 렌더링하지 않는다.
만약 다음 조건이 false 인 경우 <span>...<span> 부분 자체가 렌더링 되지 않고 사라진다.
<span th:text="'미성년자'" th:if="${user.age lt 20}"></span>
switch* 은 만족하는 조건이 없을 때 사용하는 디폴트이다.

사용 예

<table border="1">
    <tr>
        <th>count</th>
        <th>username</th>
        <th>age</th>
    </tr>
    <tr th:each="user, userStat : ${users}">
        <td th:text="${userStat.count}">1</td>
        <td th:text="${user.username}">username</td>
        <td>
            <span th:text="${user.age}">0</span>
            <span th:text="'미성년자'" th:if="${user.age lt 20}"></span> <span th:text="'미성년자'" th:unless="${user.age ge 20}"></span>
        </td>
    </tr>
</table>
<h1>switch</h1>
<table border="1">
    <tr>
        <th>count</th>
        <th>username</th>
        <th>age</th>
    </tr>
    <tr th:each="user, userStat : ${users}">
        <td th:text="${userStat.count}">1</td>
        <td th:text="${user.username}">username</td>
        <td th:switch="${user.age}">
            <span th:case="10">10살</span> <span th:case="20">20살</span> <span th:case="*">기타</span>
        </td>
    </tr>
</table>

출력


11. 주석

주석사용
표준 HTML 주석자바스크립트의 표준 HTML 주석은 타임리프가 렌더링 하지 않고, 그대로 남겨둔다.
타임리프 파서 주석타임리프 파서 주석은 타임리프의 진짜 주석이다. 렌더링에서 주석 부분을 제거한다.
타임리프 프로토타입 주석HTML 주석에 약간의 구문을 더했다.
HTML 파일을 웹 브라우저에서 그대로 열어보면 HTML 주석이기 때문에 이 부분이 웹 브라우저가 렌더링하지 않는다.
타임리프 렌더링을 거치면 이 부분이 정상 렌더링 된다.
HTML 파일을 그대로 열어보면 주석처리가 되지만, 타임리프를 렌더링 한 경우에만 보이는 기능이다.

사용 예

<h1>예시</h1>
<span th:text="${data}">html data</span>
<h1>1. 표준 HTML 주석</h1>
<!--
<span th:text="${data}">html data</span>
 -->

<h1>2. 타임리프 파서 주석</h1>
<!--/* 
[[${data}]]
 */-->
<!--/*-->
    <span th:text="${data}">html data</span>
<!--*/-->
<h1>3. 타임리프 프로토타입 주석</h1>
<!--/*/
    <span th:text="${data}">html data</span>
 /*/-->

출력


12. 블록

  • <th:block> 은 HTML 태그가 아닌 타임리프의 유일한 자체 태그다.
  • 타임리프의 특성상 HTML 태그안에 속성으로 기능을 정의해서 사용하는데, 여러 태그를 반복할 경우 사용 한다. <th:block> 은 렌더링시 제거된다.

사용 예

<th:block th:each="user : ${users}">
  <div>
    사용자 이름1 <span th:text="${user.username}"></span>
    사용자 나이1 <span th:text="${user.age}"></span>
  </div>
  <div>
    요약 <span th:text="${user.username} + ' / ' + ${user.age}"></span>
  </div>
</th:block>

출력


13. 자바스크립트 인라인

  • 자바스크립트에서 타임리프를 편리하게 사용
  • <script th:inline="javascript"> 로 사용
사용설명
텍스트 렌더링var username = [[${user.username}]];
인라인 사용 전 var username = userA;
인라인 사용 후 var username = "userA";
내추럴 템플릿var username2 = /[[${user.username}]]/ "test username";
인라인 사용 전 var username2 = /userA/ "test username";
인라인 사용 후 var username2 = "userA";
객체var user = [[${user}]];
인라인 사용 전 var user = BasicController.User(username=userA, age=10);
인라인 사용 후 var user = {"username":"userA","age":10};
each[# th:each="user, stat : ${users}"]

사용 예

<!-- 자바스크립트 인라인 사용 전 -->
<script>
    var username = [[${user.username}]];
    var age = [[${user.age}]];
    //자바스크립트 내추럴 템플릿
    var username2 = /*[[${user.username}]]*/ "test username";
    //객체
    var user = [[${user}]];
</script>
<!-- 자바스크립트 인라인 사용 후 -->
<script th:inline="javascript">
    var username = [[${user.username}]];
    var age = [[${user.age}]];
    //자바스크립트 내추럴 템플릿
    var username2 = /*[[${user.username}]]*/ "test username";
    //객체
    var user = [[${user}]];
</script>

<!-- 자바스크립트 인라인 each -->
<script th:inline="javascript">
    [# th:each="user, stat : ${users}"]
    var user[[${stat.count}]] = [[${user}]];
    [/]
</script>

출력


14. 템플릿 조각

  • 공통 부분을 다른 페이지에서 불러 사용할 수 있다.
  • ~{...} 로 사용한다. 파라미터 전달이 없으면 생략가능
  • fragment 의 이름으로 페이지를 불러올 수 있다.
사용설명
부분 포함 insert<div th:insert="~{template/fragment/footer :: copy}"></div>
현재 div 태그안에 불러온다.
부분 포함 replace<div th:replace="~{template/fragment/footer :: copy}"></div>
현재 태그를 교체한다.
파라미터 사용<div th:replace="~{template/fragment/footer :: copyParam ('데이터1', '데이터2')}"></div>
파라미터를 전달

사용 예

  • footer 템플릿 조각
<footer th:fragment="copy">
  푸터 자리 입니다.
</footer>
<footer th:fragment="copyParam (param1, param2)">
  <p>파라미터 자리 입니다.</p>
  <p th:text="${param1}"></p>
  <p th:text="${param2}"></p>
</footer>
  • 템플릿 조각 불러오기
<h1>부분 포함</h1>
<h2>부분 포함 insert</h2>
<div th:insert="~{template/fragment/footer :: copy}"></div>

<h2>부분 포함 replace</h2>
<div th:replace="~{template/fragment/footer :: copy}"></div>

<h2>부분 포함 단순 표현식</h2>
<div th:replace="template/fragment/footer :: copy"></div>

<h1>파라미터 사용</h1>
<div th:replace="~{template/fragment/footer :: copyParam ('데이터1', '데이터2')}"></div>
</body>

출력


15. 템플릿 레이아웃

  • 코드 조각을 레이아웃에 넘겨서 사용 할 수 있다.
  • 기본적으로 공통 코드를 모아두고, 각 페이지 마다 필요한 정보를 추가해서 사용 할 때 사용할 수 있다.

사용 예

  • 공통 코드
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="common_header(title,links)">
  <title th:replace="${title}">레이아웃 타이틀</title>
  <!-- 공통 -->
  <link rel="stylesheet" type="text/css" media="all" th:href="@{/css/awesomeapp.css}">
  <link rel="shortcut icon" th:href="@{/images/favicon.ico}">
  <script type="text/javascript" th:src="@{/sh/scripts/codebase.js}"></script>
  <!-- 추가 -->
  <th:block th:replace="${links}" />
</head>
</html>
  • 코드 사용
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="template/layout/base :: common_header(~{::title},~{::link})">
  <title>메인 타이틀</title>
  <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
  <link rel="stylesheet" th:href="@{/themes/smoothness/jquery-ui.css}">
</head>
<body>
메인 컨텐츠
</body>
</html>

출력

  • 전달한 <title> 로 교체
  • 추가부분에 전달한 <link> 태그 추가

16. 템플릿 레이아웃 상속

  • <html> 전체로 적용할 수 있다.
  • 기본 레이아웃에 컨텐츠 내용이 달라질 경우 사용

사용 예

  • 기본 레이아웃
<!DOCTYPE html>
<html th:fragment="layout (title, content)" xmlns:th="http://www.thymeleaf.org">
<head>
  <title th:replace="${title}">레이아웃 타이틀</title>
</head>
<body>
<h1>레이아웃 H1</h1>
<div th:replace="${content}">
  <p>레이아웃 컨텐츠</p>
</div>
<footer>
  레이아웃 푸터
</footer>
</body>
</html>
  • 사용 페이지
<!DOCTYPE html>
<html th:replace="~{template/layoutExtend/layoutFile :: layout(~{::title}, ~{::section})}"
      xmlns:th="http://www.thymeleaf.org">
<head>
  <title>메인 페이지 타이틀</title>
</head>
<body>
<section>
  <p>메인 페이지 컨텐츠</p>
  <div>메인 페이지 포함 내용</div>
</section>
</body>
</html>

출력

  • 기본 레이아웃에서 타이틀과 내용이 변경
profile
물흐르듯 개발하다 대박나기

0개의 댓글