Thymeleaf

Seung·2021년 12월 26일
0
post-thumbnail

Thymeleaf

공식 사이트: https://www.thymeleaf.org/

공식 메뉴얼 - 기본 기능: https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html
공식 메뉴얼 - 스프링 통합: https://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.html

특징

1. 서버 사이드 HTML렌더링 (SSR)
2. 내츄럴 템플릿 (순수한HTML을 유지)
3. 스프링 통합지원

타임리프 사용선언

	<html xmls:th="https://thymeleaf.org">
    

기본표현식


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

  • text / utext

    • th:text / [[...]]
      기본적인 텍스 출력 방법

      <span th:text="${data}">여기 텍스트가 data로 대체</span>
      <span>[[$data]]</span>
    • th:utext / [{...}]
      Escape기능(HTML엔티티로 변경하는 기능)을 의도적으로 사용하지
      않을 때 사용

      <span th:utext="${data}">여기 텍스트가 data로 대체</span>
      <span>[{$data}]</spna>
  • 변수 SpringEL

    • ${...}
      변수를 사용할 때는 사용

      Object (모델객체명 : user)
        <span th:text="${user.username}">여기에 대체</span>
        <span th:text="${user.['username']}">여기에 대체</span>
        <span th:text="${user.getUsername()}">여기에 대체</span>

      List (모델객체명 : users)
        <span th:text="${users[0].username}">여기에 대체</span>
        <span th:text="${users[0].['username']}">여기에 대체</span>
        <span th:text="${users[0].getUsername()}">여기에 대체</span>

      Map (모델객체명 : userMap)
        <span th:text="${userMap.username}">여기에 대체</span>
        <span th:text="${userMap.['username']}">여기에 대체</span>
        <span th:text="${userMap.getUsername()}">여기에 대체</span>
        
  • 지역변수

    • th:with
      지역변수를 선언하여 지역변수 선언언한 태그 안에서만 사용

      <div th:with="local=${users[0]">
        <p>리스트 첫번째 유저명은 <span th:text="$local.username}"></span></p>
       </div>
      
  • 기본객체들

    • ${#request}
    • ${#response}
    • ${#session}
    • ${#servletContext}
    • ${#locale}
  • URL 링크

    • @{...}
      URL을 생성할 때 사용

    ${param1} = data1 / ${param2} = data2

    단순URL

    @{/hello} 
    결과 => /hello

    쿼리 파라미터

    @{/hello(param1=${param1}, param2=${param2})} 
    결과 => /hello?param1=data1&param2=data2

    경로변수

    @{/hello/{param1}/{param}(param1=${param1}, param2=${param2})} 
    결과 => /hello/data1/data2

    경로변수 + 쿼리 파라미터

    @{/hello/{param1}(param1=${param1}, param2=${param2})}
    결과 => /hello/data1?param2=data2
  • 리터럴
    문자/숫자/불리언(boolean)/널(null)이 존재 하는데
    해당 리터럴은 '리터럴'(작은따음표)로 감싸야한다.

    " A~Z / a~z / 0~9 / [] / . / _ / - / " 해당 항목들은
    하나의 의미있는 토큰으로 인지하여 생략이 가능

    <span th:text="hello world!"></span>
    -> 오류 공백이 있어 하나의 토큰으로 간주되지 않음
    
    <span th:text="'hello world!'"></span>
    -> '(작은 따음표 사용하여 처리)
    
    <span th:text="|hello world!|"></span>
    -> | 사용하여 리터럴 대체
    
  • 연산
    Java의 연산과 비슷함
    HTML엔티티 사용하는 부분만 확인

    • 비교연산

      > : (gt)
      < : (lt)
      >= : (ge)
      <= : (le)
      ! : (not)
      == : (eq)
      != : (neq,ne)
      
    • No-Operation : _ (언더바) 사용시 타임리프가 실행되지 않는 것 처럼 동작

  • 속성 값 설정

    • th:*
      속성을 적용하면 기존의 속성을 대체


      속성 설정

      <input type="text" name="html" th:name="thymeleaf" />
      결과 => 해당 name은 thymeleaf로 처리

      속성 추가

      <input type="text" class="html" th:attrappend="class=' back'" />
      결과 => 해당 attrappend 사용시 class는 'html back'로 처리
      
      <input type="text" class="html" th:attrprepend="class='front '" />
      결과 => 해당 attrprepend 사용시 class는 'front html'로 처리
      
      <input type="text" class="html" th:classappend="replace" />
      결과 => 해당 classappend 사용시 class는 'replace'로 처리

      checked 처리

      <input type="checkbox" name="active" checked="false" />
      => html에서는 이경우에도 속성에 checked가 존재하여 check처리가 된다.
      
      <input type="checkbox" name="active" th:checked="false" />
      => thymeleaf 사용시 th:checked="false" 인 경우 checked 속성을 제거한다.
  • 반복

    • th:each

    반복기능

    <tr th:each="user : ${users}">
      <td th:text="${user.username}">유저명</td>
      <td th:text="${user.age}">나이</td>
    </tr>
    
    th:each	는 List,배열,java.util.Iterable,java.util.Enumeration,Map에서 사용가능
    Map은 변수에 담기는 값은 Map.Entry이다

    반복상태

    <tr th:each="user, userStat : ${users}">
      <td th:text="${userStat.count}">1번부터시작</td>
      <td th:text="${userStat.index}">0번부터 시작</td>
      <td th:text="${userStat.size}">전체사이즈</td>
      <td th:text="${userStat.even}">홀수여부(true/false)</td>
      <td th:text="${userStat.odd}">짝수여부(true/false)</td>
      <td th:text="${userStat.first}">처음여부(true/false)</td>
      <td th:text="${userStat.last}">마지막여부(true/false)</td>
      <td th:text="${userStat.current}">현재객체</td>
    </tr>
  • 조건식

    • if / unless (if의 반대)

      age : 10 일때
      <span th:text="'미성년자'" th:if="${user.age lt 20}"></span>
      결과 => lt 는 '<'  이므로 10 < 20 true  미성년자 출력
      
      <span th:text="'미성년자'" th:if="${user.age lt 20}"></span>
      결과 => ge 는 '>=' 이므로 10 >= 20 false 이므로 아무것도 출력안함
      
      <span th:text="'미성년자'" th:unless="${user.age lt 20}"></span>
      결과 => ge 는 '>=' 이므로 10 >= 20 false 인데 
      unless는 if의 반대이므로 true로 미성년자 출력
      
    • switch

    age : 10일때
    <td th:switch="${user.age}">
      <span th:case="10">10살</span>
      <span th:case="20">20살</spna>
      <span th:case="*">기타</span>
    </td>
    결과 => age가 10이기에 10살이 출력
    *은 만족하는 조건이 없을 때 사용하는 디폴트 값
  • 주석

    1.html 표준 주석 <!--  -->
    자바스크립트의 표준 html주석은 렌더링 하지 않고 남겨둔다.
    
    2.타임리프 주석 <!--/*   */-->
    타임리프 파서 주석은 타임리프의 진짜 주석으로 렌더링시 주석부분을 제거
    
    3.타임리프 프로토타입 주석 <!--/*/   /*/-->
    타임리프를 거치지 않으면 html주석이므로 html표준 주석과 동일하게 작동
    타임리프 렌더링시 해당 내용이 출력된다.
  • 블록

    • <th:block>
      HTML태그가 아닌 타임리프의 유일한 자체 태그
    <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>
      
      반복문을 블록단위로 묶어 출력시 사용
  • 자바스크립트 인라인

    • <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 = class명.User(~~~~);  
        사용후 결과-> var user = {"username":"userA","age":10};
        사용전 : toString()이 호출된 값 / 사용후 : 객체를 JSON으로 변환
        -자바스크립트 인라인 each (반복)
        <script th:inline="javascript">
          [# th:each="user, stat : ${users}"]
          var user [[${stat.count}]] = [[${user}]];
          [/]
        </script>
  • 템플릿 조각
    웹페이지 개발시 공통영역에 함께 사용하는 영역을 보다 편리하게 지원

    • 푸터html
        <footer th:fragment="copy">
        푸터자리
        </footer>
        <footer th:fragment="copyParam(param1, param2)">
        <p th:text="${param1}"></p>
        <p th:text="${param2}"></p>
    • 푸터사용html
      부분포함 insert
      <div th:insert="~{푸터경로/fragment/footer :: copy}"></dvi>
      부분포함 replace
      <div th:replace="~{푸터경로/fragment/footer :: copy}"></div>
      부분포함 단순 표현식
      <div th:replace="푸터경로/fragment/footer :: copy"></div>
      파라미터사용
      <div th:replace="~{푸터경로/fragment/footer :: copyParam('데이터1','데이터2')}"></div>
  • 템플릿 레이아웃
    head, css, javascript등 공통 정보를 한 곳에 사용하고,
    각 페이지마다 추가 정보를 추가시 사용

    • 공통head (base.html)

      <html xmlns:th="http://www.thymeleaf.org">
      <head th:fragment="common_header(title,links)">
        <title th:replace="${title}">레이아웃 타이틀</title>
        
        <!-- 공통 -->
        공통헤더들
        <!-- 추가 -->
        <th:block th:replace="${links}" />
      </head>
    • 공통헤더 사용

      <html xmlns:th="https://www.thymeleaf.org">
      <head th:replace="공통헤더경로/base :: common_header(~{::title},~{::link})">
        <title>메인타이틀</title>
        <!-- 추가 헤더 -->
        <link rel="stylesheet" th:href="@{/css/bootstrap.main.css}">
        </head>
      <bodt>
      메인컨텐츠
      </body>
      </html>
      
      결과 => 공통헤더와 추가헤더가 추가되어 적용
      메인타이틀이 전달한 부분으로 교체 ::{link},~{::link}는 현재 페이지의
      해당태그를 전달
      
    • 공통html (layoutFile)

      <html th:fragment="layout(title,content)" xmlns:th="http://www.thymeleaf.org">
        <head>
          <title th:replace="${title}">레이아웃 타이틀</title>
        </head>
        <body>
          <h1>레이아웃</h1>
          <div th:replace="${content}">
            <p>레이아웃 콘텐츠</p>
          </div>
          <footer>
            레이아웃푸터
          </footer>
        </body>
      </html>
    • 공통html사용

      <html th:replace="~{공통html경로/layoutFile :: layout(~{::title},~{::section})}" xmlns:th="http://www.thymeleaf.org">
        <head>
          <title>메인 타이틀</title>
        </haed>
        <body>
          <section>
            <p>메인 컨텐츠</p>
            </div> 메인 내용</div>
          </section>
      </body>
      </html>
      
    • 결과

      <html>
      <head>
        <title>메인 타이틀</title>
        <body>
          <h1>레이아웃</h1>
          <section>
            <p>메인 컨텐츠</p>
            <div>메인 내용 </div>
          </section>
          <footer>
            레이아웃 푸터
          </footer>
        </body>
        </html>
        => 공통html에 th:fragment속성이 정의되어 있다
           해당 레이앗울 기본으로 하고 여기에 필요한 내용을 전달해서 부분변경
      
        =>공통사용html은 현재페이지 section태그를 공통html에 content로 넘겨 사용
profile
한번 해봅시다.

0개의 댓글