타임 리프 기본 기능

타임 리프

  • 백엔서드 동적으로 HTML을 만들어주는 JSP와 같은 템플릿 엔진

특징

  • 네츄럴 템플릿
    • 타임리프는 작성한 파일은 순수 HTML을 유지 한다. 타임리프 파일을 그대로 열어도 정상적으로 브라우저에서 렌더링 된다
    • JSP와 같은 템플릿 엔진은 브라우저에서 열면 해당 JSP 코드를 브라우저가 해석하지 못해 HTML이 깨진다
  • 스프링 통합 지원
    • 스프링과 자연스러운 통합되고, 스프링의 다양한 편리한 기능을 사용할 수 있다

사용 선언

<html xmlns:th="http://www.thymeleaf.org">

텍스트 출력 - text, utext

  • text
    <li>th:text 사용 <span th:text="${data}"></span></li> // html 엘리먼트에 삽입
    
    <li>[[${data}]]</li> // 인라인 텍스트
  • utext (Unescape text)
    • HTML에서 사용하는 특수 문자를 문자로 볼 수 있게 처리하는걸 Escape라고 함 기본적으 text는 excape 처리 함

    • utext는 태그를 문자가 아닌 태그로 처리할 수 있게 함 즉 escape 처리를 하지않은 unescape임

      <li>th:text 사용 <span th:utext="${data}"></span></li> // utext
      
      <li>[(${data})]</li> // [()]

변수 - Spring El

  • Object
<span th:text="${user.username}"></span> // 필드 접근
<span th:text="${user.getUsername()}"></span> // 게터 접근
<span th:text="${user['username']}"></span> // 자바스크립트처럼 프로퍼티 접근
  • List
    • 인덱스에 접근 할 수 있다
<span th:text="${users[0].username}"></span> 
<span th:text="${users[0].getUsername()}"></span> 
<span th:text="${users[0]['username']}"></span> 
  • Map
    • 자바스크립트 객체 프로퍼티 접근 처럼 할 수 있다

      <span th:text="${userMap['userA'].username}"></span>
      <span th:text="${userMap['userA'].getUsername()}"></span>
      <span th:text="${userMap['userA']['username']}"></span>
  • 지역 변수
    • th:with 를 사용하면 지역변수는 선언된 태그안에서만 사용 가능하다

      <div th:with="first=${users[0]}"> 
          <p>처음 사람의 이름은 <span th:text="${first.username}"></span></p>
      </div>

타임리프에서 제공하는 기본 객체들

  • 식 기본 객체 (Expression Basic Objects)
    <li>request = <span th:text="${#request}"></span></li>
    <li>request = <span th:text="${#response}"></span></li>
    <li>request = <span th:text="${#session}"></span></li>
    <li>request = <span th:text="${#servletContext}"></span></li>
    <li>request = <span th:text="${#locale}"></span></li>
  • 편의 객체
    <li>Request Parameter = <span th:text="${param.paramData}"></span></li> // 파라미트 접근
    <li>Session = <span th:text="${session.sessionData}"></span></li> // 세션 접근
    <li>spring bean = <span th:text="${@helloBean.hello('spring!')}"></span></li> // 빈 접근

유틸리티 객체와 날짜

URL 링크

  • 타임리프에서 URL 생성할 때 @{...} 문법을 사용하면 된다
  • 단순한 URL
    • @{/hello} → /hello
  • 쿼리 파라미터
    • @{/hello(param1=${param1}, param2='babo')} → /hello?param1=data1¶m2=babo
  • 경로 변수
    • @{/hello/{param1}/{param2}(param1=${param1}, param2=${param2})} → /hello/data1/data2
  • 경로 변수 + 쿼리 파라미터
    • @{/hello/{param1}(param1=${param1}, param2=${param2})} → /hello/data1?param2=data

리터럴

  • 리터럴은 변수가 아닌 그 값 자체를 리터럴이라고 함
  • 타임리프에는 4가지의 리터럴 값이 있음
    • 문자 : 'hello'
    • 숫자 : 10
    • 불린 : true , false
    • null : null
  • 주의할 점은 타임리프에서 문자는 ' (작음 따옴표)로 깜싸야 함
    • but 공백 없이 쭉 이어진다면 하나의 의미있는 토큰으로 인지해 작은 따옴표 생략
      • ex) <span th:text="hello">
    • but 중간에 공백이 있으면 하나의 토큰으로 인식 되지 않아 작은 따옴표로 감싸야 한다
      • ex) <span th:text="hello world"><span th:text="'hello world'">
  • 리터럴 대체
    • 리터럴 대체 문법을 사용하면 작은 따옴표 없이도 편하게 사용가능 하다
      • ex) <span th:text="|hello ${data}|">
        • 이게 가장 깔끔하게 실수를 방지하는기 좋은거 같다 내 개인적인 생각에는 모든 텍스트에 이걸 적용하는게 좋을거 같다

연산

  • 산술 연산
    • > (gt)
    • < (lt)
    • >= (ge)
    • <= (le)
    • !(not)
    • == (eq)
    • != (neq, ne)
  • 삼항 연산
    • ex) (10 % 2 == 0) : '짝수' : '홀수'
  • Elvis 연산자
    • ex) ${data}?: '데이터가 없습니다'
    • datanull 이아니면 data 를 출력하고 null이면 '데이터가 없습니다' 출력
    • 자바스크립트 data || '데이터가 없습니다' 버전 인거 같다.
  • No - Operation
    • ex) ${data}?:_
    • data 가 있으면 data 출력 없으면 아무것도 안함
    • _ 언더바 임

속성값 설정

  • 타임리프 속성
    • 타임리프 속성은 th:* 를 이용해 속성을 지정함
    • th:* 속성을 지정하면 기존 속성을 지정한 속성으로 대체 한다. 기존 속성이 없다면 새로 만든다
      • ex) <input name="mock" th:name="userA"/><input name="userA" />
  • 속성 추가
    • th:attrappend
      • html의 기존 속성 뒤에 추가하는 방식이다
      • 주의점은 기존 속성과 겹치치지 않게 속성 값 앞에 띄워쓰기를 해줘야 한다
      • ex) <input type="text" class="text" th:attrappend="class=' large'" /><input type="text" class="text" large />
    • th:attrprepend
      • html의 기존 속성 앞에 추가하는 방식이다
      • 마찬가지로 기존 속성값과 겹치지 않게 뒤에 띄워쓰기를 해줘야 한다
      • ex) <input type="text" class="text" th:attrprepend="class='large '" /><input type="text" class="large text" />
    • th:classappend
      • ex) <input type="text" class="text" th:classappend="large"><input type="text" class="large text" />
      • 클래스를 추가할 일이 있으면 위에 속성보다 그냥 이거 쓰자 실수를 할 확률도 줄고 무엇보다 보기도 편하고 간편하다
  • chcked 처리
    <input type="checkbox" name="active" th:checked="true">

반복

<tr th:each="user: ${users}">
    <td th:text="${user.username}"></td>
    <td th:text="${user.age}"></td>
</tr>
  • 타임리프는 반복 루프에 대한 상태를 확인할 수 있음
  • index : 0부터 시작하는 값
  • count : 1부터 시작하는 값
  • size : 전체 사이즈
  • event , odd : 홀수 짝수 여부 boolean 값으로 제공
  • first , last : 처음, 마지막 여부 boolean 값으로 제공
  • current : 현재 객체
<tr th:each="user, stat: ${users}">
    <td th:text="${user.username}"></td>
    <td th:text="${user.age}"></td>
		<td th:text="${stat.index}"></td>
</tr>

조건부 평가

  • if, unless
    • th:if 는 조건을 만족하면 해당 태그를 렌더링 한다

    • th:unlessth:if 의 부정이라고 생각하면 된다

      <tr th:each="user, userStat : ${users}">
          <td th:text="${userStat.count}"></td>
          <td th:text="${user.username}"></td>
          <td>
              <span th:text="${user.age}"></span>
              <span th:text="'미성년자'" th:if="${user.age lt 20}"></span>
              <span th:text="'미성년자'" th:unless="${user.age ge 20}"></span>
          </td>
      </tr>
  • switch
    • switchcase 조건에 부합되는 태그만 렌더링 한다

      <tr th:each="user, userStat : ${users}">
          <td th:text="${userStat.count}"></td>
          <td th:text="${user.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>

주석

  • 타임리프 파서 주석
    • 타임리프 기본 주석

    • 타임리프 파서 주석을 사용할 경우 아예 렌더링에서 제거 함

      <!--/*-->
      <span th:text="${data}"></span>
      <!--*/-->
      
      <!--/* [[${data}]] */-->
  • 프로토타입 주석
    • HTML 파일을 통짜로 열 경우 주석처리가 되지만

    • 타임리프 렌더링을 거치면 정상 렌더링 된다

    • 강사님이 쓸일이 없다는데 내 생각도 별로 쓸 때까 생각이 안난다

      <!--/*/
      <span th:text="${data}"></span>
      /*/-->

블록

  • 타임리프의 유일한 자체 태그이다
  • 타임리프 특성상 태그안에 th:* 를 정의해서 사용하는데 태그 없이 사용하기 좋다
<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>
</th:block>

자바스크립트 인라인

  • 타임리프 안에서 자바스크립트를 편리하게 사용할 수 있는 기능이다
  • 자바스크립트 인라인 사용 전
    <script>
        const username = [[${user.username}]];
        const age = [[${user.age}]];
    
        const user = "[[${user}]]";
    </script>
    • 문자열 같은 경우 따로 자바스크립트 문법에 맞게 "" 쌍 따옴표로 감싸야 한다. 깜빡하고 쌍따옴표로 안 감싼다면 바로 자바스크립트 문법 오류 가 난다 굉장히 불편하다
    • 또한 객체의 경우 toString 으로 변환되서 나오기 때문 아예 사용이 불가능하다
  • 인라인 사용 후
    <script th:inline="javascript">
        const username = [[${user.username}]];
        const age = [[${user.age}]];
    
        const user = [[${user}]];
    </script>
    • 인라인을 사용하면 문자열 같은 경우 자동적으로 자바스크립트 문법에 맞게 변환 시켜준다
    • 객체같은 경우 자바스크립트 객체(JSON)로 변환 시켜준다
    • 또한 자바스크립트에서 문제가 될 수 있는 문자가 있으면 이스케이프 처리도 해준다
  • 인라인 each
    <script th:inline="javascript">
        [# th:each="user, stat: ${users}"]
        var user[[${stat.count}]] = [[${user}]];
        [/]
    </script>
    • 자바스크립트에서 타임리프 반복문을 사용할 때 사용하면 된다

템플릿 조각

  • 웹 페이지를 개발할 때 공통 영역이 많이 있다. 공통 된 부분의 코드를 복사해서 사용하면 유지보수에 어려움에 있다. 이런 문제를 해결하기 위해 타임리프는 템플릿 조각과, 레이아웃 기능을 지원한다
  • 템플릿 선언
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <html lang="en">
    <body>
    <footer th:fragment="copy">
        푸터 자리 입니다.
    </footer>
    <footer th:fragment="copyParam (param1, param2)">
        <p>파라미터 자리 입니다.</p>
        <p th:text="${param1}"></p>
        <p th:text="${param2}"></p>
    </footer>
    </body>
    </html>
    • 조각 파일을 만들면 사용하는 곳에서 함수 처럼 불러다 사용할 수 있다
    • 함수 처럼 파라미터도 적용할 수 있다
  • 템플릿 사용
    <h2>부분 포함 insert</h2>
    <div th:insert="~{template/fragment/footer :: copy}"></div>
    
    <h2>부분 포함 replace</h2>
    <div th:replace="~{template/fragment/footer :: copy}"></div>
    
    <h2>부분 포함 단순 표현식</h2>
    <div th:replace="template/fragment/footer :: copy"></div>
    
    <h1>파라미터 사용</h1>
    <div th:replace="template/fragment/footer :: copyParam ('data1', 'data2')"></div>

템플릿 레이 아웃

  • 이전에는 일부 코드 조각을 만들어 함수 처럼 만들어 사용했다면 레이 아웃을 만들어 사용할 수 있다
  • 레이아웃 만들기
    <html xmlns:th="http://www.thymeleaf.org">
    <head th:fragment="common_header(title, links)">
        <title th:replace="${title}">레이아웃 타이틀</title>
    
    <!--    공통-->
        <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}" />
    </head>
    • common_header 매개변수로 받은 titlelink
  • 레이아웃 사용하기
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <html lang="en">
    <head th:replace="template/layout/base :: common_header(~{::title}, ~{::link})">
      <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>
    • th:replace 를 이용하여 템플릿을 사용한다 인수로 받을때는 교체되는 태그를 ~{::**} 방식으로 선언한다 인수의 이름과 레이아웃의 교체되는 태그가 같아야 한다

좋은 웹페이지 즐겨찾기