2. Thymeleaf 기본

한승록·2024년 8월 18일
0

HTML 기초

목록 보기
2/2
post-thumbnail
※ 인프런 김영한님 강의를 본인의 이해를 바탕으로 작성한 글이므로 사용법에 틀린 부분이 존재할 수 있습니다.

1. 특징

  • 서버사이드 HTML 렌더링
  • 네츄럴 템플릿
  • 스프링 통합 지원

1-1. 서버사이드 HTML 렌더링

  • HTML을 동적으로 렌더링 하는 용도로 사용

1-2. 네츄럴 템플릿

  • 순수 HTML을 최대한 유지하는 특징
  • JSP 등 다른 뷰 템플린과 다르게 서버를 통해서 렌더링이 진행되어야 확인이 가능

1-3. 스프링 통합 지원

  • 스프링과 자연스럽게 통합



2. 사용방법

2-1. 선언

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

2-2. 기본 표현식

1) 텍스트 출력

  • th:text
  • 예시
    		ex) <span th:text="${data}"></span>
    		ex) <span>[[${data}]]</span>
  • HTML 엔티티
    • 이스케이프(Escape) : 특수 문자를 HTML 엔티티로 변경하는 행위
    • 타임리프가 제공하는 th:text와 [[...]]은 기본적으로 이스케이프를 제공
  • Unescape
    • th:utext와 [(...)]를 제공

2) 변수(SpringEL)

  • 예시
    	<!-- ex) Object -->
    	${user.username} / ${user['username']} / ${user.getUsername()}
    	<!-- ex) List -->
    	${users[0].username} / ${users[0]['username']} / ${users[0].getUsername()}
    	<!-- ex) Map -->
    	${userMap['userA'].username} / ${user['userA']['username']} / ${user['userA'].getUsername()}
  • 지역변수 선언
    • th:with
    • 예시
      <div th:with="first=${users[0]}"></div>

3) 기본 객체

  • 기본 객체(Expression Basic Objects)
    <input th:text=${#request} />
    <input th:text=${#response} />
    <input th:text=${#session} />
    <input th:text=${#servletContext} />
    <input th:text=${#locale} />
    <!-- 결과 : 해당 객체의 주소값이 나옴 -->
  • 편의 객체(Expression Basic Objects)
    <!-- model 값 접근 -->
    <input th:text="${#param.paramData}" />
    <!-- session 값 접근 -->
    <input th:text="${#session.sessionData}" />
    <!-- bean으로 등록된 값에 직접 접근 -->
    <input th:text="${@helloBean.hello('Spring!')}" />
    -> 해당 객체의 데이터 값이 나옴

4) 유틸리티 객체

  • 유틸리티 객체
    -> 타임리프에서 상용할 수 있는 자료형이나 Collection의 내장 메서드를 사용 가능하게 지원
  • 날짜
    -> 유틸리티 객체와 마찬가지로 Date나 LocalDateTime 등의 formatter 같은 기능을 사용할 수 있음

5) URL 링크

  • th:href
  • 기본 URL
    	<link th:href="@{/hello}" >
  • 쿼리 파라미터
    	<link th:href="@{/hello(param1=${param1}, param2=${param2})}" >
  • 경로변수
    	<link th:href="@{/hello/{param1}}" >
  • 경로 변수 + 쿼리 파라미터
    	<link th:href="@{/hello/{param1}}/param1=${param1}, param2=${param2})" >

6) 리터럴

  • 소스 코드 상 고정된 값을 말하는 용어
  • 문자, 숫자, boolean, null
  • ex)
      <input th:text="'hello' + ' world!'" />
      <input th:text="'hello world!'" />
      <input th:text="'hello ' + ${data}" />
      <input th:text="|hello ${data}|" />
  • 예외 : 공백 없이 쭉 이어진다면 하나의 의미있는 값으로 인지하여 따옴표 생략 가능 -> 즉 ''없이 띄워쓰기 시 파싱 오류가 발생

7) 연산

  • 자바와 동일
  • Elvis 연산자 : 조건식의 편의 버전
  • No-Operation : '_'의 경우 마치 타임리프가 작동하지 않는 것 처럼 동작
    -> ex)
    <span th:text = "${data}?: _">데이터가 없습니다.</span>
    <!-- 데이터가 없을 경우 text가 그대로 출력 -->

8) 속성 설정

  • 속성을 지정하면 타임리프는 기존 속성을 th:로 대체

  • ex)

    <input type="text" name="user" th:name="thUser" />
  • 속성 추가
    -> 띄워쓰기가 중요

    <input class="normal" th:attrappend="class=' append'" />
    <!-- class="normal" 에서 class="normal large"로 추가 -->
    
    <input class="normal" th:attrprepend="class='large '" />
    <!-- class="normal" 에서 class="large normal"로 추가 -->
    
    <input class="normal" th:classappend="class=' large'" />
    <!-- class="text" 에서 class="text large"로 추가 -->
  • checked 처리

    <input type="checkbox" name="check" th:checked="true" />
    <input type="checkbox" name="check" th:checked="false" />
    <input type="checkbox" name="check" checked="false" />

9) 반복

  • th:each

  • ex)

    <tr th:each="user : ${users}">
    	<td th:text="${user.username}"></td>
    	<td th:text="${user.age}"></td>
    </tr>
  • 배열, Iterable, Enumeration, Map까지 사용 가능
    -> Map의 경우 변수에 담기는 값은 Map.Entry

  • 반복 상태

    <tr th:each="user, userStatus : ${users}">

    -> 두번째 파라미터 설정을 통해 상태확인 가능

    <tr th:text="${userStatus.index}">
    <tr th:text="${userStatus.count}">
    <tr th:text="${userStatus.size}">
    <tr th:text="${userStatus.even}"> <!-- boolean -->
    <tr th:text="${userStatus.odd}"> <!-- boolean -->
    <tr th:text="${userStatus.first}"> <!-- boolean -->
    <tr th:text="${userStatus.last}"> <!-- boolean -->
    <tr th:text="${userStatus.current}"> <!-- 현재 값 -->

    -> 두번째 파라미터는 생략가능하며 생략 시 변수 + Stat을 활용


10) 조건문

  • th:if
  • th:unless
  • th:switch, th:case

11) 주석

  • 표준 HTML 주석
    <!-- -->
  • 타임리프 파서 주석
    <!--/* */--> <!-- 한줄 -->
    <!--/* --> <!-- */--> <!-- 범위 -->
    -> 렌더링 시 해당 부분 제거
  • 타임리프 프로토타입 주석
    <!--/*/ /*/-->
    -> 타임리프로 렌더링 된 경우에만 표시

12) 블록

  	<th:block th:each="user : ${users}"></th:block>
  • 타임리프의 유일한 자체 태그로 HTML에서는 제공하지 않음
  • ex)
    <th:block th:each="user : ${users}">
    	<div>${user.name}</div>
    	<div>${user.age}</div>
    </th:block>
  • 순수 HTML에서 제공하지 않는 만큼 사용을 지양하는것이 좋음

13) 자바스크립트 인라인

	<script th:inline="javascript">
  • ex) 기본
    	// model 접근
    	var username = "[[${user.username}]]";
    	// 자바스크립트 내추럴 템플릿
    	var username = /*[[${user.username}]]*/;
    	// 객체
    	var user = [[${user}]];
    	// => toString()의 형태로 전달 ex) Controller.User(키=값)
  • ex) 인라인
    // model 접근
    var username = [[${user.username}]];
    // 자바스크립트 내추럴 템플릿
    var username = /*[[${user.username}]]*/;
    // 객체
    var user = [[${user}]];
  • 텍스트 렌더링 : ""를 붙여주지 않아도 렌더링
  • 객체 렌더링 : JSON으로 자동 변환
  • th:each 사용 가능
    [# th:each="user, stat : ${users}"]
    	var user[[${stat.count}]] = [[${user}]]
    [/]

14) 템플릿 조각

  • th:fragment
  • 선언
    <footer th:fragment="copy"></footer>
    <footer th:fragment="copyParam (param1, param2)">
      <p th:text="${param1}"></p>
      <p th:text="${param2}"></p>
    </footer>
  • 사용 방법
    <!-- 포함 : div가 유지 -->
    <div th:insert="~{template/fragment/footer :: copy}">
    <!-- 부분 포함 : div를 footer로 대체 -->
    <div th:replace="~{template/fragment/footer :: copy}">
    <!-- 부분 포함 단순 표현식 -->
    <div th:replace="template/fragment/footer :: copy">
    <!-- 파라미터 사용 : 해당 값을 형식에 맞춰 렌더링 -->
    <div th:replace="~{template/fragment/footer :: copyParam ('데이터1', '데이터2')}">

15) 템플릿 레이아웃

  • 공통으로 사용하는 정보들을 레이아웃에 넘겨 적용

  • 기본
    -> 선언

      <head th:fragment="commmonHeader(title, links)">
        <title th:replace="${title}">레이아웃 타이틀</title>
    
        <!-- 공통 -->
        <link>
        <script></script>
    
        <!-- 추가 -->
        <th:block th:replace="${links}" />
      </head>

    -> 적용

      <head th:replace="template/layout/base :: common_header(~{::title}, ~{::link})">
        <title>개별 타이틀</title>
        <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}" />
      </head>
  • 확장
    -> 선언

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

    -> 적용

      <html th:replace="~{template/layoutExtend/layoutFile :: layout(~{::title}, ~{::section})}"
            xmlns:th="http//www.thymeleaf.org">
출처 : [스프링 MVC 2편 - 백엔드 웹 개발 활용 기술](인프런)
profile
개발 학습

0개의 댓글