0. 이전 기본 문법
- <html xmlns:th="http://www.thymeleaf.org">
 - 타임리프 사용 선언
 
- 타임리프 사용 선언
- th : PROPERTY = " @{} or ${} or | | or ( )"
- PROPERTY ex: name, class 같은거 의미
- 타임리프는 th:로 타임리프 문법이 시작된다.
- th에 적용할 property를 쓰고 " " 내부에 적용하고 싶은 문법을 적용한다.
- 어지간한 property는 다 th: property 종류 가능하다.
- th: property를 해도 그냥 property도 작성을 하는데
 이는 렌더링 전에는 그냥 property가 적용되고
 렌더링 후에는 th: property가 적용된다.
 
- @{} : url 경로
- ${} : controller로 부터 받아온 model 객체의 key를 작성하면 value를 반환해줌
- | | : 리터럴로 JS의 벡틱 같은 역할이라고 보면 된다.
- 타임리프에서 문자와 표현식 등은 분리되어 있기 때문에 더해서 사용
 <span th:text="'Welcome to our application, ' + ${user.name} + '!'">
 <span th:text="|Welcome to our application, ${user.name}!|">
 
- 타임리프에서 문자와 표현식 등은 분리되어 있기 때문에 더해서 사용
- ()
- @{} 내부에서 model로받아온 정보를 변수를 설정해서 pathvariable로 사용하고 싶을 때
- 쿼리 파라미터도 사용 가능
 th:href="@{/basic/items/{itemId}(itemId=${item.id}, query='test')}"
 생성 링크: http://localhost:8080/basic/items/1?query=test
 
- th:each
 반복문
 
1. 타임리프 특징
- SSR
- natural template : 순수 html을 최대한 유지하는 특징을 가짐
- 스프링 통합 지원
2. 기본 기능

- 타임리프 사용 선언 : <html xmlns:th="http://www.thymeleaf.org">
- 참고: https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#standard-expression-syntax
• 간단한 표현:
    ◦ 변수 표현식: ${...}
    ◦ 선택 변수 표현식: *{...}
    ◦ 메시지 표현식: #{...}
    ◦ 링크 URL 표현식: @{...}
    ◦ 조각 표현식: ~{...}
• 리터럴
    ◦ 텍스트: 'one text', 'Another one!',…
    ◦ 숫자: 0, 34, 3.0, 12.3,…
    ◦ 불린: true, false
    ◦ 널: null
    ◦ 리터럴 토큰: one, sometext, main,…
• 문자 연산:
    ◦ 문자 합치기: +
    ◦ 리터럴 대체: |The name is ${name}|
• 산술 연산:
    ◦Binary operators: +, -, *, /, %
    ◦Minus sign (unary operator): -
• 불린 연산:
    ◦Binary operators: and, or
    ◦Boolean negation (unary operator): !, not
• 비교와 동등:
    ◦ 비교: >, <, >=, <= (gt, lt, ge, le)
    ◦ 동등 연산: ==, != (eq, ne)
• 조건 연산:
    ◦If-then: (if) ? (then)
    ◦If-then-else: (if) ? (then) : (else)
    ◦Default: (value) ?: (defaultvalue)
• 특별한 토큰:
    ◦No-Operation: _
3. text,utext

- text
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
        lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>컨텐츠에 데이터 출력하기</h1>
<ul>
    <li>th:text 사용 = <span th:text="${data}"></span></li>
    <li>컨텐츠 안에서 직접 출력하기 = [[${data}]]</li>
</ul>
</body>
</html>
- utext
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<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>
  <li>[[...]] = [[${data}]]</li>
  <li>[(...)] = [(${data})]</li>
</ul>
</body>
</html>
- 텍스트 - text
- html content에 data를 출력할 때 사용
- th:text="${data}"
- [[${data}]]
 
- html content에 data를 출력할 때 사용
- 텍스트 - utext
- html tag의 속성이 아닌 html content 안에서 직접 데이터를 출력하고 싶을 경우 사용
- th:text="${data}" -> th:utext="${data}"
- [[${data}]] -> [(${data})]
 
- html tag의 속성이 아닌 html content 안에서 직접 데이터를 출력하고 싶을 경우 사용
4. meta 특징
4.1. Escape

- http 요청으로 들어온 값에서 html 형식의 code(특수문자: <,>,$,@)가 존재시 컴퓨터는 이를 html로 인식할지 아니면 그 자체를 문자로 인식해야될지 모른다.  그래서 thymeleaf는 default로 특수문자를 문자로 인식하기로 했다.
- model로부터 받아온 값은 client가 작성한 값인 경우가 많은데 이 때 사용자들이 <> 등등 별의 별걸 다 써서 이스케이프로 태그 처리되는 문제를 막을 필요가 있다.
- HTML 태그를 문자로 표현할 수 있는 방법을 HTML 엔티티라고 한다. <  =  <    >  =  >
- 특수문자를 HTML 엔티티로 변경하는 과정을 Escape라고 한다.
- th:text="<b>abc</b>" 이렇게 변수 표현식이 아닌 값이 직접 들어온 경우 에러난다.
- 작동 순서
- http 요청 params data : "<b> Spring! <b>"
- thymeleaf 인코딩(Escape 수행) : <span th:text="${data}"></span> - 눈에는 안보임
- th:text="${data}" -> th:text= "<b> Spring! <b>" 으로 나타남 -> UI에서 escape 된다.
 
- UI 나타남: <b>Spring</b>
- 소스코드 : <b> Spring! <b> 이 아니라 th:text="<b>Spring</b>" 로 변경됨.
- 이유: < > 해당 특수기호를 실제 문자 형식으로 UI에 나타내고 싶기 때문, <b>로 적혀있으면 UI 표현시 html 코드로 인식해서 굵은 글씨로 바꿔버림
 
 
4.2. Unescape

- escape 기능을 사용하지 않기 위해서 thymeleaf가 제공하는 기능이 존재한다.
- 이런 기능이 있다는 것을 보여주기 위함이고 꼭 필요시만 사용할 것
text - utext 차이점 - 중괄호 대괄호
- text 표현 방식 2가지
- th:text="${data}"
- [[${data}]]   :   [  [  ]  ]
 
- utext 표현 방식 2가지
- th:utext="${data}"
- [(${data})] : [ ( ) ]
 
기타
th:inline="none" : 중괄호 대괄호를 thymeleaf 코드로 해석하지 말라는 설정
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<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>
  <li>[[...]] = [[${data}]]</li>
  <li>[(...)] = [(${data})]</li>
</ul>
</body>
</html>
5. 변수 - SpringEL

- 변수 - SpringEL: spring이 제공하는 표현식을 사용 가능
- ${...} : Object, List, Map 으로 들어온 data 모두 처리 가능 + 지역변수도 가능
- 지역 변수는 해당 tag 내부에서만 작동
//object
th:text="${user.username} == [[${user.username}]]
th:text="${user['username']}" == [[${user['username']}]]
th:text="${user.getUsername()}" == [[${user.getUsername()}]]
//List
th:text="${users[0].username}"
th:text="${users[0]['username']}"
th:text="${users[0].getUsername()}"
//Map
th:text="${userMap['userA'].username}"
th:text="${userMap[userA]['username']}"
th:text="${userMap[userA].getUsername()}"
//지역변수 th:with
th:with="first=${users[0]}"      // first라는 지역변수
	th:text="${first.username}"  // 지역변수는 선언한 태그 내에서만 사용 가능
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>SpringEL 표현식</h1>
<ul>Object
    <li>${user.username} = <span th:text="${user.username}"></span></li>
    <li>${user.username} = <span>[[${user.username}]]</span></li>
    <p></p>
    <li>${user['username']} = <span th:text="${user['username']}"></span></li>
    <li>${user['username']} = <span>[[${user['username']}]]</span></li>
    <p></p>
    <li>${user.getUsername()} = <span th:text="${user.getUsername()}"></span></li>
    <li>${user.getUsername()} = <span>[[${user.getUsername()}]]</span></li>
</ul>
 <p th:inline="none"> List, Map 도 [[]] 동일하게 작용, th:inline="none" 사용 주의<p/>
<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]['username']} = <span th:text="${userMap[userA]['username']}"></span></li>
    <li>${userMap[userA].getUsername()} = <span th:text="${userMap[userA].getUsername()}"></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}"> 1st 사람이름 </span></p>
</div>
</body>
</html>
5. 기본 객체

- url
http://localhost:8080/basic/basic-objects?paramData=HelloParam
- controller : spring 3.0 이후부터 Moel에 담아서 보내줘야한다.
@GetMapping("/basic-objects")
public String basicObjects(Model model, HttpServletRequest request, HttpServletResponse response, HttpSession session){
    session.setAttribute("sessionData", "Hello Session");
    model.addAttribute("request", request);
    model.addAttribute("response", response);
    model.addAttribute("servletContext", request.getServletContext());
    return "basic/basic-objects";
}
@Component("helloBean")
static class HelloBean{
    public String hello(String data){
        return "Hello " + data;
    };
}
- 스프링 부트 3.0 이전
- controller에서 model에 따로 기본 객체를 담지 않아도 thymeleaf에서 제공
 
<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>
- 스프링 부트 3.0 이후
- thymeleaf에서 일부 제공 안함. controller에서 model에 따로 기본 객체를 담아야한다.
 
// 3.0 이후에도 제공하는 것들
<span th:text="${request}"></span>
<span th:text="${response}"></span>
<span th:text="${servletContext}"></span>
// 3.0 이후에도 제공하는 것들
// session은 기본 제공되지만 ${#session} -> ${session} 으로 변경
<span th:text="${session}"></span>
<span th:text="${#locale}"></span>
- 편의 객체
 하도 자주 써서 제공해주는 것- params: request.getParameter("paramData") 필요 없음 -> 대신 url에서 query문이 들어와야함
- session: controller에 session.setAttribute("sessionData", "Hello Session"); 넣어야 함
- 스프링 bean 접근: @로 접근
 
<span th:text="${param.paramData}"></span>
<span th:text="${session.sessionData}"></span> 
<span th:inline="none"> * session.setAttribute("sessionData", "Hello Session"); 필요</span></li>
<span th:text="${@helloBean.hello('spring!')}"></span>
6. thymeleaf 유틸리티 객체
- ${#유틸리티명.필요method}
유틸리티 종류
- #message : 메시지, 국제화 처리
- #uris : URI 이스케이프 지원
- #dates : java.util.Date 서식 지원
- #calendars : java.util.Calendar 서식 지원
- #temporals : 자바8 날짜 서식 지원
- #numbers : 숫자 서식 지원
- #strings : 문자 관련 편의 기능
- #objects : 객체 관련 기능 제공
- #bools : boolean 관련 기능 제공
- #arrays : 배열 관련 기능 제공
- #lists, #sets, #maps : 컬렉션 관련 기능 제공
- #ids : 아이디 처리 관련 기능 제공, 뒤에서 설명
타임리프 유틸리티 객체
 https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#expression-utility- objects
유틸리티 객체 예시
 https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#appendix-b-expression- utility-objects
존재 정도만 파악하고 필요시 찾아보기
6.1. #temporals : 자바8 날짜 서식 지원
- spring menual에 존재하지 않아서 작성
- springboot-thymeleaf에 해당 library가 내장되어있다.
- controller
- model에 model.addAttribute("localDateTime", LocalDateTime.now()); 추가
 
1. "localDateTime" default로 사용
${#temporals.format(localDateTime, 'yyyy-MM-dd HH:mm:ss<변경가능>')}
2. temporals util 사용
<span th:text="${#temporals.day(localDateTime)}"></span>
<span th:text="${#temporals.month(localDateTime)}"></span>
<span th:text="${#temporals.monthName(localDateTime)}"></span>
<span th:text="${#temporals.monthNameShort(localDateTime)}"></span>
<span th:text="${#temporals.year(localDateTime)}"></span>
<span th:text="${#temporals.dayOfWeek(localDateTime)}"></span>
<span th:text="${#temporals.dayOfWeekName(localDateTime)}"></span>
<span th:text="${#temporals.dayOfWeekNameShort(localDateTime)}"></span>
<span th:text="${#temporals.hour(localDateTime)}"></span>
<span th:text="${#temporals.minute(localDateTime)}"></span>
<span th:text="${#temporals.second(localDateTime)}"></span>
<span th:text="${#temporals.nanosecond(localDateTime)}"></span>
7. url 링크
- 중요
- @{...} 사용
- cf) spring bean의 ${@...} 랑 다름
 
- controller
@GetMapping("/link")
public String link(Model model){
    model.addAttribute("param1", "data1");
    model.addAttribute("param2", "data2");
    return "basic/link";
}
종류 4가지
- 기본 role
- () : queary params
- ${}  : pathvariable, 경로변수로 이용, 물론 () 내부에 경로변수로 사용될 변수들이 존재해야한다. 
 
- th:href="@{/hello}" : 해당 url로 이동
- http://localhost:8080/hello
 
- th:href="@{/hello(param1=${param1}, param2=${param2})}" : 해당 url로 이동 + query문도 넣음
- http://localhost:8080/hello?param1=data1¶m2=data2
 
- th:href="@{/hello/{param1}/{param2}(param1=${param1}, param2=$ {param2})}" : 해당 url로 이동, 경로변수 넣기
- http://localhost:8080/hello/data1/data2
 
- th:href="@{/hello/{param1}(param1=${param1}, param2=$ {param2})}" : 경로변수, query 문 혼합
- http://localhost:8080/hello/data1?param2=data2
 
8. literals
- 문자: 'hello'
- 숫자: 10
- boolean: true , false
- null: null
- 실수 자주 하는 부분
- thymeleaf에서 문자 리터럴은 항상 '' 로 감싸야한다. -> 공백없이 이어나가는 문자에 한해서 생략해도 가능
- 공백 없이 쭉 이어진다면 하나의 의미있는 토큰으로 인지해서 다음과 같이 작은 따옴표를 생략할 수 있다.
 룰: A-Z , a-z , 0-9 , [] , . , - , _
 
- literals 대체
- | ... | : 공백 상관없이 그냥 막써도 됨 ex)</span th:text="|hello ${data}|">
 
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>리터럴</h1>
<ul>
<!--  예외 코드 - thymeleaf 문자 리터럴은 '' 없을 때 뛰어쓰기 불가 - 토큰이 인식 못함-->
<!--  <li>"hello world!" = <span th:text="hello world!"></span></li>-->
  <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>
</body>
</html>
9. 연산
- th 내부에서 연산을 하였을 때
- 비교 연산자나 일반 연산자 결과 까지 작성시 boolean으로 값 반환
- 일반 연산만 작성할 경우 값 반환
// 산술 연산
<li>10 +2 = <span>[[10+2]]</span></li> // 10 +2 = 12
<li>10 % 2 == 0 = [[10 % 2 == 0]]</li> // 10 % 2 == 0 = true
//비교연산
<li> 10 > 1 = [[10 > 1]]</li>       // 10 > 1 = true
<li> 10 gt 1 = [[10 gt 1]]</li>     // 10 gt 1 = true
<li> 10 > 1 = [[10 > 1]]</li> // 10 > 1 = true
<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>
- 조건식, Elvis 연산자, No-Operation
// 조건식
<li>(10 %2 ==0) ? '짝수': '홀수' = <span th:text="(10 %2 ==0) ? '짝수': '홀수' "></span></li> // 짝수
// elvis 연산자
<li>${data}? : 'data 없음' = <span th:text="${data}?:'data 없음'"></span></li> // Spring
// No-Operation
<li>${data}?: _ = <span th:text="${data}?: _">data 없음</span></li> // Spring
<li>${data}?: _ = <span th:text="${nullData}?: _">data 없음</span></li> // data 없음
- 비교연산: HTML 엔티티를 사용해야 하는 부분을 주의
-  > (gt),  < (lt),  >= (ge),  <= (le),  ! (not),  == (eq),  != (neq, ne)
 
-  > (gt),  < (lt),  >= (ge),  <= (le),  ! (not),  == (eq),  != (neq, ne)
- 조건식: 자바의 조건식과 유사
- Elvis 연산자: 조건식의 편의 버전  
- No-Operation:  _ 인 경우 마치 타임리프가 실행되지 않는 것 처럼 동작한다. 이것을 잘 사용하면 HTML
 의 내용 그대로 활용할 수 있다.
10. 속성 값 설정
- 속성 설정
- th:* 지정한 속성으로 대체, 기존 속성 없을 시 새로 생성
 
- th:* 지정한 속성으로 대체, 기존 속성 없을 시 새로 생성
- 속성 추가
- th:attrappend - 속성 값의 뒤에 값을 추가 , 띄어쓰기 필요
- th:attrprepend - 속성 값의 앞에 값을 추가 . 띄어쓰기 필요
- th:classappend  - class 속성에 자연스럽게 추가 , 띄어쓰기 자동
 
- checked 처리
- html checked="false" - checked 속성이 존재하기 때문에 checked 처리 되어버림
- thymeleaf
- th:checked="false" - checked 속성 자체를 제거
- th:checked="true" - checked 속성 유지
 
 
- html checked="false" - checked 속성이 존재하기 때문에 checked 처리 되어버림
<!-- 속성 설정 -->
<input type="text" name="mock" th:name="userA">
<!-- 속성 추가 -->
- 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"/>
<!-- checked 처리 -->
- 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"/>
11. 반복

- th:each
- th:each="user : ${users}"
- List, array, Iterable, Enumeration, Map 까지 사용 가능
 Map의 경우 Map.Entry 작동
 
- userStat
- th:each의 2번째 params 이고 생략 가능, 생략시 변수명은 (1st 변수명) + Stat 가 된다.
- Stat 기능
- index : 0부터 시작하는 값
- count : 1부터 시작하는 값
- size : 전체 사이즈
- even , odd : 홀수, 짝수 여부( boolean )
- first , last :처음, 마지막 여부( boolean )
- current : 현재 객체
 
 
<tr th:each="user, userStat : ${users}"> // userStat 생략 가능
    <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>
12. 조건부 평가 - java 문법과 동일
- if, unless : return 이 false인 경우 태그 자체가 렌더링 되지 않고 사라진다.
- switch: *은 만족하는 조건이 없을 때 사용하는 값이다.

@GetMapping("/condition")
public String condition(Model model){
    addUsers(model);
    return "basic/condition";
}
private void addUsers(Model model) {
        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);
}<!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: ${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="미성년자111" th:if="${user.age < 20}"></span>
      <span th:text="미성년자222" th:unless="${user.age > 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>
13. 주석
- 표준 html 주석
- <!-- 주석 처리 내용 -->
 
- 타임리프 파서 주석 : 자주 사용, 렌더링된 html 파일에서는 소스코드에 나타나지도 않음 
- <!--/* 주석 처리 내용 */-->
- <!--/*--> 주석 처리 내용 <!--*/-->
 
- 타임리프 프로토타입 주석 : rendering html에서는 값으로 나오고 static 일때 주석처리됨
- <!--/*/ 주석 처리 내용 /*/-->
 
<h1>1. 표준 html 주석</h1>
<!--
<span th:text="${data}">html data</span>
-->
<h1>2. thymeleaf html 주석 - 2가지: 렌더링된 html 파일에서는 소스코드에 나타나지도 않음</h1>
<p>1)</p>
<!--/*-->
<span th:text="${data}">html data</span>
<!--*/-->
<p>2)</p>
<!--/*[[${data]] */-->
<h1>3. 타임리프 프로토타입 주석: rendering html에서는 나오고 static 일때 주석처리됨</h1>
<!--/*/
<span th:text="${data}">html data</span>
/*/-->
14. 블록
- thymeleaf의 유일한 자체 태그
- div n개 동시에 each loop 돌리고 싶을 때 사용
- 웬만하면 사용하지 말고 꼭 필요할 때만 사용
- <th:block th:each="user : ${user}"> ~ </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>
15. 자바스크립트 인라인

- <script th:inline="javascript">
- 인라인 존재 유무 차이점
- text 렌더링
-  var username = [[${user.username}]];
 - 인라인 사용 전 결과 : var username = userA;
- 인라인 사용 후 결과 : var username = "userA"; // 문자 타입인 경우 " " 포함 해준다. escape 처리도 가능
 
 
-  var username = [[${user.username}]];
- javaScript natural templete
-  var username2 = /*[[${user.username}]]*/ "test username";
- 인라인 사용 전 var username2 = /*userA*/ "test username"; // 그대로 해석
- 인라인 사용 후    var username2 = "userA"; // 주석 부분 제거 하고 내부 실제 tyhemleaf 코드(=원하는 렌더링) 잘 적용
 
 
-  var username2 = /*[[${user.username}]]*/ "test username";
- 객체
- var user = [[${user}]];
- 인라인 사용 전 var user = BasicController.User(username=userA, age=10); // toString 호출값
- 인라인 사용 후    var user = {"username":"userA","age":10}; // JSON으로 변환
 
 
- var user = [[${user}]];
- 자바스크립트 인라인 each 
 [# th:each="user, stat : ${users}"] ...[ / ]
<script th:inline="javascript">
    [# th:each="user : ${users}"]
    const user[[${userStat.count}]] = [[${user}]];
    [/]
</script>
16. 템플릿 조각


주요 속성 3가지
- th:fragment - 해당 tag가 조각이라고 지정
- th:insert - fragment를 받는 부분, fragment를 받는 tag 내부에 fragment로 지정된 tag를 받는다.
- th:replace - fragment를 받는 부분, fragment를 받는 tag를 날리고 fragment tag 자체를 받는다.
- th:text - fragment를 받는 부분 해당 tag를 escape 시킨다.
th:fragment : 다른 곳에 포함되는 코드 조각으로 이해
fragment 지정 == footer.html == 다른 곳의 코드 조각
- params 없는 경우
- params 있는 경우
fragment 사용 방법
-  ~{url :: fragment 명(params)} 
- fragment 명은 꼭 필수값은 아니다. 하지만 어떤 역할인지 파악하기가 좋다.
 
- fragment가 없더라도 ~{url :: tag} 를 통해서 fragment 전달가능
- 이 경우 해당 tag가 여러개 일때 원하는 것을 지정할 수 없다.
 
- cf) ~{}로 감싸지 않아도 되지만 url 복잡해지면 감싸야 함
- 부분 포함
- insert : frgment를 부른 tag를 건들이지 않고 내부에 생성
- replace : fragment를 부른 tag를 제거하고 생성
 
- 파라미터 사용
- ('파라미터에 들어갈 값1', '파라미터에 들어갈 값2' ): params 값은  필수로 다 들어가야함
 
- ('파라미터에 들어갈 값1', '파라미터에 들어갈 값2' ): params 값은  필수로 다 들어가야함
<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>단순 표현식 - 가능하지만 url이 복잡해지면 ~{::} 사용해야함 </h2>
	<div th:replace="template/fragment/footer :: copy"></div>
<h1>파라미터 사용</h1>
	<div th:replace="~{template/fragment/footer :: copyParam ('데이터1', '데이터2')}"></div>
17. 템플릿 레이아웃 1
- 템플릿 조각 수준에서 더 큰 규모로 접근
- 큰 규모로 공통부분을 넣어주고 개별적으로 가지고 싶은 부분은 개별적으로 넣는 방법
방식
- head tag를 fragment 지정함. fragment를 지정할 때 params를 받도록 지정을 한다. - params를 받는 부분이 개별적으로 추가하는 부분이다. -> 해당 head fragment를 사용할 때 params를 넣어줘야한다. 해당 params는 다른 html부터 받음.
- params부분은 UI에 나올 html의 title과 link들 을 추가해준다. - 현재 html의 title,link를 넣을 것이므로 ~{::title}, ~{::link} 설정하고 url 작성은 필요 없음
순서
- UI html 의 head 부분을 layout head로 교체
- 교체된 head 부분에서 UI로 부터 받은 params를 주입
// UI에 나올 html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="template/layout/base :: common_header(~{::title},~{::link})">
			<!--자기 자신의 tag를 params로 보내는 거여서 url 작성 필요 X-->
    <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>
// head layout을 공유하는 html - 
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="common_header(title,links)">
    <title th:replace="${title}">레이아웃 타이틀</title>
    <!--UI html로부터 tag 자체를 받아오기때문에 th:text가 아닌 th:replace로 받아 온다.-->
    <!--공통-->
    <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}" />
    <!--UI html로 부터 link tag 자체를 받아 온것이므로 th:replace 사용-->
</head>
<body></body>
</html>
// source code
<!DOCTYPE html>
<html>
<head>
    <title>메인 타이틀</title>
    <!--공통-->
    <link rel="stylesheet" type="text/css" media="all" href="/css/awesomeapp.css">
    <link rel="shortcut icon" href="/images/favicon.ico">
    <script type="text/javascript" src="/sh/scripts/codebase.js"></script>
    <!--추가 -->
    <link rel="stylesheet" href="/css/bootstrap.min.css">
    <link rel="stylesheet" href="/themes/smoothness/jquery-ui.css">>
</head>
<body>
메인 컨텐츠
</body>
</html>
18. 템플릿 레이아웃 2
- 템플릿 레이아웃 1과 원리 동일
- 그냥 범위만 더 넓혀서 html 수준에서 fragment 하는 것

사용 적기
- fragment: html page 수가 적을 때 사용
- template layout: html page 수가 많을 때 사용