web Language/html

1. 타임리프 - 기본기능

wooweee 2023. 5. 5. 13:22
728x90

0. 이전 기본 문법

 

  1. <html xmlns:th="http://www.thymeleaf.org">
    • 타임리프 사용 선언

  2. 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. 기본 기능

 

 

더보기

• 간단한 표현:
    ◦ 변수 표현식: ${...}
    ◦ 선택 변수 표현식: *{...}
    ◦ 메시지 표현식: #{...}
    ◦ 링크 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}]]

 

  • 텍스트 - utext
    • html tag의 속성이 아닌 html content 안에서 직접 데이터를 출력하고 싶을 경우 사용

    • th:text="${data}" -> th:utext="${data}"
    • [[${data}]] -> [(${data})]

 

 

4. meta 특징

 

4.1. Escape

 

  • http 요청으로 들어온 값에서 html 형식의 code(특수문자: <,>,$,@)가 존재시 컴퓨터는 이를 html로 인식할지 아니면 그 자체를 문자로 인식해야될지 모른다.  그래서 thymeleaf는 default로 특수문자를 문자로 인식하기로 했다.

  • model로부터 받아온 값은 client가 작성한 값인 경우가 많은데 이 때 사용자들이 <> 등등 별의 별걸 다 써서 이스케이프로 태그 처리되는 문제를 막을 필요가 있다.

  • HTML 태그를 문자로 표현할 수 있는 방법을 HTML 엔티티라고 한다. &lt;    >  =  &gt;

  • 특수문자를 HTML 엔티티로 변경하는 과정을 Escape라고 한다.

  • th:text="<b>abc</b>" 이렇게 변수 표현식이 아닌 값이 직접 들어온 경우 에러난다.

 

  • 작동 순서
    1. http 요청 params data : "<b> Spring! <b>"
    2. thymeleaf 인코딩(Escape 수행) : <span th:text="${data}"></span> - 눈에는 안보임
      • th:text="${data}" -> th:text= "<b> Spring! <b>" 으로 나타남 -> UI에서 escape 된다.
    3. UI 나타남: <b>Spring</b>
      • 소스코드 : <b> Spring! <b> 이 아니라 th:text="&lt;b&gt;Spring&lt;/b&gt;" 로 변경됨.
      • 이유: < > 해당 특수기호를 실제 문자 형식으로 UI에 나타내고 싶기 때문, <b>로 적혀있으면 UI 표현시 html 코드로 인식해서 굵은 글씨로 바꿔버림

 

 

4.2. Unescape

 

  • escape 기능을 사용하지 않기 위해서 thymeleaf가 제공하는 기능이 존재한다.
  • 이런 기능이 있다는 것을 보여주기 위함이고 꼭 필요시만 사용할 것

 

text - utext 차이점 - 중괄호 대괄호

  • text 표현 방식 2가지
    1. th:text="${data}"
    2. [[${data}]]   :   [  [  ]  ]

  • utext 표현 방식 2가지
    1. th:utext="${data}"
    2. [(${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>

 

  • 편의 객체
    하도 자주 써서 제공해주는 것
    1. params: request.getParameter("paramData") 필요 없음 -> 대신 url에서 query문이 들어와야함
    2. session: controller에 session.setAttribute("sessionData", "Hello Session"); 넣어야 함
    3. 스프링 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, 경로변수로 이용, 물론 () 내부에 경로변수로 사용될 변수들이 존재해야한다. 

  1. th:href="@{/hello}" : 해당 url로 이동
    • http://localhost:8080/hello
  2. th:href="@{/hello(param1=${param1}, param2=${param2})}" : 해당 url로 이동 + query문도 넣음
    • http://localhost:8080/hello?param1=data1&param2=data2
  3. th:href="@{/hello/{param1}/{param2}(param1=${param1}, param2=$ {param2})}" : 해당 url로 이동, 경로변수 넣기
    • http://localhost:8080/hello/data1/data2
  4. 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 내부에서 연산을 하였을 때
  1. 비교 연산자나 일반 연산자 결과 까지 작성시 boolean으로 값 반환
  2. 일반 연산만 작성할 경우 값 반환
// 산술 연산
<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 &gt; 1 = [[10 &gt; 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)

  • 조건식: 자바의 조건식과 유사

  • Elvis 연산자: 조건식의 편의 버전  

  • No-Operation:  _ 인 경우 마치 타임리프가 실행되지 않는 것 처럼 동작한다. 이것을 잘 사용하면 HTML
    의 내용 그대로 활용할 수 있다.

 

10. 속성 값 설정

 

  1. 속성 설정
    • th:* 지정한 속성으로 대체, 기존 속성 없을 시 새로 생성

  2. 속성 추가
    1. th:attrappend    - 속성 값의 뒤에 값을 추가 , 띄어쓰기 필요
    2. th:attrprepend   - 속성 값의 앞에 값을 추가 . 띄어쓰기 필요
    3. th:classappend  - class 속성에 자연스럽게 추가 , 띄어쓰기 자동

  3. checked 처리
    1. html checked="false" - checked 속성이 존재하기 때문에 checked 처리 되어버림

    2. thymeleaf
      1. th:checked="false" - checked 속성 자체를 제거
      2. th:checked="true" - 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. 반복

 

 

  1. th:each
    • th:each="user : ${users}"
    • List, array, Iterable, Enumeration, Map 까지 사용 가능
      Map의 경우 Map.Entry 작동
  2. 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 문법과 동일

  1. if, unless : return 이 false인 경우 태그 자체가 렌더링 되지 않고 사라진다.
  2. 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. 주석

  1. 표준 html 주석
    1. <!-- 주석 처리 내용 -->
  2. 타임리프 파서 주석 : 자주 사용, 렌더링된 html 파일에서는 소스코드에 나타나지도 않음 
    1. <!--/*  주석 처리 내용  */-->
    2. <!--/*-->  주석 처리 내용  <!--*/-->
  3. 타임리프 프로토타입 주석 : rendering html에서는 값으로 나오고 static 일때 주석처리됨
    1. <!--/*/  주석 처리 내용  /*/-->
 
<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">

 

  • 인라인 존재 유무 차이점

  1. text 렌더링
    •  var username = [[${user.username}]];
      • 인라인 사용 전 결과 : var username = userA
      • 인라인 사용 후 결과 : var username = "userA"; // 문자 타입인 경우 " " 포함 해준다. escape 처리도 가능

  2. javaScript natural templete
    •  var username2 = /*[[${user.username}]]*/ "test username";
      • 인라인 사용 전    var username2 = /*userA*/ "test username";  // 그대로 해석
      • 인라인 사용 후    var username2 = "userA"; // 주석 부분 제거 하고 내부 실제 tyhemleaf 코드(=원하는 렌더링) 잘 적용

  3. 객체
    • var user = [[${user}]];
      • 인라인 사용 전    var user = BasicController.User(username=userA, age=10); // toString 호출값
      • 인라인 사용 후    var user = {"username":"userA","age":10}; // JSON으로 변환

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

 

 

16. 템플릿 조각

 

 

주요 속성 3가지

  1. th:fragment - 해당 tag가 조각이라고 지정

  2. th:insert - fragment를 받는 부분,    fragment를 받는 tag 내부에 fragment로 지정된 tag를 받는다.
  3. th:replace - fragment를 받는 부분, fragment를 받는 tag를 날리고 fragment tag 자체를 받는다.

  4. th:text - fragment를 받는 부분 해당 tag를 escape 시킨다.

 

 

th:fragment : 다른 곳에 포함되는 코드 조각으로 이해

 

fragment 지정 == footer.html == 다른 곳의 코드 조각

  1. params 없는 경우
  2. params 있는 경우
 

 

fragment 사용 방법

  •  ~{url :: fragment 명(params)} 
    • fragment 명은 꼭 필수값은 아니다. 하지만 어떤 역할인지 파악하기가 좋다.
  • fragment가 없더라도 ~{url :: tag} 를 통해서 fragment 전달가능
    • 이 경우 해당 tag가 여러개 일때 원하는 것을 지정할 수 없다.
  • cf) ~{}로 감싸지 않아도 되지만 url 복잡해지면 감싸야 함

 

  1. 부분 포함
    1. insert : frgment를 부른 tag를 건들이지 않고 내부에 생성
    2. replace : fragment를 부른 tag를 제거하고 생성

  2. 파라미터 사용
    • ('파라미터에 들어갈 값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 작성은 필요 없음 

순서

  1. UI html 의 head 부분을 layout head로 교체
  2. 교체된 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 하는 것

 

 

사용 적기

  1. fragment: html page 수가 적을 때 사용
  2. template layout: html page 수가 많을 때 사용

 

 

 

다음 발행글: [Thymeleaf] - 2. thymeleaf - 스프링 통합과 폼