월루를 꿈꾸는 대학생

[MVC-2] 타임리프 본문

Programing/Spring Boot

[MVC-2] 타임리프

하즈시 2023. 8. 8. 21:51
728x90

메뉴얼
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

타임리프 특징
  • 서버 사이드 html 랜더링 ssr
  • 네츄럴 템플릿
  • 스프링 통합 지원
서버사이드 html 랜더링
  • 타임리프는 백엔드 서버에서 html 동적으로 랜더링
네츄럴 템플릿
  • html 파일을 순수하게 유지하려고 함 = 파일만 열어도 안 깨짐
  • 서버를 통해 뷰 템플릿을 동적으로 변경하고 값을 덮어씌워서 랜더링함

    순수 html을 유지하면서 뷰 템플릿도 사용할 수 있는 것을 네츄럴 템플릿이라고 한다

스프링 통합 지원
  • 스프링과 통합이 아주 잘 되어 있음
타임리프 기본 기능
타임리프 선언
<html xmlns:th="http://www.thymeleaf.org">

기본 표현식
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#standard-expression-syntax


텍스트

  • th:text
  • text 태그를 사용해도 되고 , 그냥 영역 안에 [[ ... ]] 넣으면 인식해서 쓰기 가능
<span th:text="${data}">
<ul>  
    <li>th:text 사용 <span th:text="${data}"></span></li>  
    <li>컨텐츠 안에서 직접 출력하기 = [[${data}]]</li>  
</ul>
ESCAPE
  • html은 < , > 같은 특문 기준 정의
  • 저기 컨트롤러에서 <\b> Spring <\b> 이렇게 문자열로 모델 세팅해도 html 받으면 저 태그가 다르게 바뀜

  • 소스코드 보면 < 이게 < 이래됨
HTML 엔티티
  • html은 < 요걸 태그의 시작으로 인식함 그래서 이걸 문자로 인식할 표현이 필요함 = html엔티티
  • html에서 특수문자를 html엔티티로 변경하는 것 = 이스케이프
  • [[\ ]] 요거 쓰면 기본적인 이스케이프 제공해줌

->즉 그냥 문자인식으로 바꿔주는 건데 지금 bold 하고 싶으니까 unescape 해야함

UNESCAPE
  • th:text -> th:utext
  • [[...]] -> [(...)]

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

<li>th:text = <span th:text="${data}"></span></li>  
<li>th:utext = <span th:utext="${data}"></span></li>

이스케이프를 디폴트로 쓰자 -> 정상 랜더링 안 되는 많은 문제가 야기될 수 있으니 이스케이프가 필요함


변수 - SpringEL

${...}

<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>

user.username : user의 username을 프로퍼티 접근 user.getUsername()
user['username'] : 위와 같음 user.getUsername()
user.getUsername() : user의 getUsername() 을 직접 호출

지역 변수 선언
  • th:with 를 사용해서 지역변수 선언 가능 해당 변수는 태그 안에서만 사용 가능함
    <div th:with="first=${users[0]}">
      <p>처음 사람의 이름은 <span th:text="${first.username}"></span></p>
    </div>

기본 객체들

  • 기본객체가 3.0 기준으로 좀 바뀜
  • 3.0 이상이면 기본객체는 거의 없고 그냥 model에서 넘기는 편이 좋음

유틸리티 객체와 날짜

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


URL 링크
  • @{}
<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>

리터럴
  • 소스코드 상 고정된 값
  • 문자: 'hello' : 무조건 작은 따옴표 감싸야함
  • 숫자: 10
  • 불린: true , false
  • null: null

리터럴 대체(Literal substitutions)

<span th:text="|hello ${data}|">
  • || 로 감싸는게 가장 편한듯

연산
  • 비교 연산

    • (gt), < (lt), >= (ge), <= (le), ! (not), == (eq), != (neq, ne)

      <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>
  • 조건식

    <li>(10 % 2 == 0)? '짝수':'홀수' = <span th:text="(10 % 2 == 0)?
    '짝수':'홀수'"></span></li>
  • Elvis 연산자 : 조건식 편의 버전

  • ${data}?: '데이터가 없습니다.' =
  • ${nullData}?: '데이터가 없습니다.' =
  • ```
    • No-Operation: _ 인 경우 타임리프 실행되지 않는 것처럼 동작
      <li>${data}?: _ = <span th:text="${data}?: _">데이터가 없습니다.</
      span></li>
      <li>${nullData}?: _ = <span th:text="${nullData}?: _">데이터가
      없습니다.</span></li>

    속성값 설정

    타임리프 태그 속성
    • th : ~~
    • 기존 속성을 대체
      ```html
    • th:attrappend =
    • th:attrprepend =
    • th:classappend = <input type="text" class="text" th:classappend="large" /


    check
    타임리프의 th:checked 는 값이 false 인 경우 checked 속성 자체를 제거한다.

    타임리프 렌더링 후:


    반복

    • th:each
      <tr th:each="user : ${users}">
      <td th:text="${user.username}">username</td>
      <td th:text="${user.age}">0</td>
      </tr>

    조건부 평가

    • if / unless

    주석


    블록

    <th:block>
    • div 2개나 for each로 해결하기 어려운 경우 넣어서 씀

    자바스크립트 인라인

    • 타임리프 내에서 자바스크립 사용할 수 있도록 기능을 제공
      <script th:inline="javascript">

    var username = [[${user.username}]];

    • 인라인 사용 전 var username = userA;
    • 인라인 사용 후 var username = "userA"; 인라인 사용 후 문자타입이면 "" 추가 됨
    자바스크립트 내추럴 템플릿
    • html 파일 열어도 동작

    • var username2 = /[[${user.username}]]/ "test username";

      • 인라인 사용 전 var username2 = /userA/ "test username"; : 그대로 해석
      • 인라인 사용 후 var username2 = "userA"; : 주석제거 하고 userA가 처리 됨
    • var user = [[${user}]];

      • 인라인 사용 전 var user = BasicController.User(username=userA, age=10);
      • 인라인 사용 후 var user = {"username":"userA","age":10}; : 인라인 사용 후 객체를 json 형태로 변경

    템플릿 조각


    템플릿 레이아웃

    코드조각을 레이아웃에 넘겨서 사용
    head를 공통으로 쓰고 싶은 경우 공통 정보를 모아두고 필요한 부분만 추가적으로 추가해서 사용

    common_header({::title},{::link}) 이 부분이 핵심
    ::title 은 현재 페이지의 title 태그들을 전달
    ::link 는 현재 페이지의 link 태그들을 전달

    head뿐만 아니라 html 전체에도 적용가능

    html 에 th:fragment 속성을 정의하고 해당 레이아웃 파일을 기본으로 하고 여기에 필요한 내용을 전달해서 부분부분 변경하면 됨


    출처
    https://inf.run/mc57

    728x90