
<html xmlns:th="http://www.thymeleaf.org">
HTML의 콘텐츠(content)에 데이터를 출력할 때 th:text 사용
ex) <span th:text="${data}">
HTML 테그의 속성이 아니라 HTML 콘텐츠 영역안에서 직접 데이터를 출력하고 싶을 때 [[...]] 사용
ex) 컨텐츠 안에서 직접 출력하기 = [[${data}]]
만약 Hello Spring!과 같이 Spring! 부분에 <b></b> 태그를 넣는다면 어떻게 될까?
 소스를 보게 되면
 소스를 보게 되면 Hello <b>Spring!</b> 와 같이 나오게 된다.
그렇다면 이를 어떻게 해결해야 할까?
다음과 같은 두가지 방법이 있다.
th:text -> th:utext[[...]] -> [(...)]이렇게 작성 후 실행해 보면 정상적으로 수행되는 것을 확인할 수 있다.
${...}SpringEL의 다양한 표현식
user.username : user의 username을 프로퍼티 접근 -> user.getUsername()user['username'] : 위와 같음 -> user.getUsername()user.getUsername() : user의 getUsername() 을 직접 호출users[0].username : List에서 첫 번째 회원을 찾고 username 프로퍼티 접근 -> list.get(0).getUsername()users[0]['username'] : 위와 같음users[0].getUsername() : List에서 첫 번째 회원을 찾고 메서드 직접 호출userMap['userA'].username : Map에서 userA를 찾고, username 프로퍼티 접근 -> map.get("userA").getUsername()userMap['userA']['username'] : 위와 같음userMap['userA'].getUsername() : Map에서 userA를 찾고 메서드 직접 호출타임리프는 기본적으로 다양한 객체들을 제공한다.
그 중 편의 객체는 다음과 같다.
param${param.paramData}session${session.sessionData}@${@helloBean.hello('Spring!')다양한 객체가 존재하는데 자세한 내용은 다음 링크에서 볼 수 있다.
타임리프에서 URL을 생성할 때는 @{...} 문법을 사용하면 된다.
단순한 URL
@{/hello} ->  /hello
쿼리 파라미터
@{/hello(param1=${param1}, param2=${param2})}
-> /hello?param1=data1¶m2=data2
() 에 있는 부분은 쿼리 파라미터로 처리된다.
경로 변수
@{/hello/{param1}/{param2}(param1=${param1}, param2=${param2})}
-> /hello/data1/data2
URL 경로상에 변수가 있으면 () 부분은 경로 변수로 처리된다.
경로 변수 + 쿼리 파라미터
@{/hello/{param1}(param1=${param1}, param2=${param2})}
-> /hello/data1?param2=data2
경로 변수와 쿼리 파라미터를 함께 사용할 수 있다.
예시)
<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>타임리프는 다음과 같은 리터럴이 있다.
타임리프에서 문자 리터럴은 항상 ' (작은 따옴표)로 감싸야 한다.
예시) <span th:text="'hello'">
만약 공백 없이 쭉 이어진다면 하나의 의미있는 토큰으로 인지해서 다음과 같이 작은 따옴표를 생략할 수 있다.
룰 : A-Z, a-z , 0-9 , [] , . , - , _
예시) <span th:text="hello">
비교연산 : HTML 엔티티를 사용해야 하는 부분을 주의하자,
>(gt), < (lt), >= (ge), <= (le), ! (not), == (eq), != (neq, ne)
조건식 : 자바의 조건식과 유사하다.
Elvis 연산자 : 조건식의 편의 버전
No-Operation : _ 인 경우 마치 타임리프가 실행되지 않는 것 처럼 동작한다. 이것을 잘 사용하면 HTML의 내용 그대로 활용할 수 있다. 마지막 예를 보면 데이터가 없습니다. 부분이 그대로 출력된다.
예시)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<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 > 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>
</body>
</html>실행 결과)

타임리프는 주로 HTML 태그에 th:* 속성을 지정하는 방식으로 동작한다. th:* 로 속성을 적용하면 기존 속성을 대체한다. 기존 속성이 없으면 새로 만든다.
th:* 속성을 지정하면 타임리프는 기존 속성을 th:* 로 지정한 속성으로 대체한다. 기존 속성이 없다면 새로 만든다.
<input type="text" name="mock" th:name="userA" />
-> 타임리프 렌더링 후 <input type="text" name="userA" />
th:attrappend : 속성 값의 뒤에 값을 추가한다.
th:attrprepend : 속성 값의 앞에 값을 추가한다.
th:classappend : class 속성에 자연스럽게 추가한다.
HTML에서는 <input type="checkbox" name="active" checked="false" />
-> 이 경우에도 checked 속성이 있기 때문에 checked 처리가 되어버린다.
타임리프의 th:checked 는 값이 false 인 경우 checked 속성 자체를 제거한다.
<input type="checkbox" name="active" th:checked="false" />
-> 타임리프 렌더링 후 : <input type="checkbox" name="active" />
예시 코드)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<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/>
</body>
</html>타임리프에서 반복은 th:each 를 사용한다. 추가로 반복에서 사용할 수 있는 여러 상태 값을 지원한다.
<tr th:each="user : ${users}">
th:each 는 List 뿐만 아니라 배열, java.util.Iterable , java.util.Enumeration 을 구현한 모든 객체를 반복에 사용할 수 있다. Map 도 사용할 수 있는데 이 경우 변수에 담기는 값은 Map.Entry다.<tr th:each="user, userStat : ${users}">
반복의 두번째 파라미터를 설정해서 반복의 상태를 확인 할 수 있다.
두번째 파라미터는 생략 가능한데, 생략하면 지정한 변수명( user ) + Stat 가 된다.
여기서는 user + Stat = userStat 이므로 생략 가능하다.
예시 코드)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<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>
</body>
</html>실행 화면)

if, unless
타임리프는 해당 조건이 맞지 않으면 태그 자체를 렌더링하지 않는다.
만약 다음 조건이 false 인 경우 <span>...<span> 부분 자체가 렌더링 되지 않고 사라진다.
<span th:text="'미성년자'" th:if="${user.age lt 20}"></span>
switch
* 은 만족하는 조건이 없을 때 사용하는 디폴트이다
예시 코드)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>if, unless</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>
            <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>
</body>
</html>실행 화면)

타임리프는 자바스크립트에서 타임리프를 편리하게 사용할 수 있는 자바스크립트 인라인 기능을 제공한다.
자바스크립트 인라인 기능은 다음과 같이 적용하면 된다.
<script th:inline="javascript">
var username2 = /*[[${user.username}]]*/ "test username";
var username2 = /*userA*/ "test username";var username2 = "userA";
이런 유용한 정보를 나눠주셔서 감사합니다.