개발/Spring

[Spring 프로젝트] Spring Boot에서 타임리프(Thymeleaf) 사용하기

nova_dev 2020. 11. 12. 11:33
반응형

 

Spring 
Spring Boot에서 타임리프(Thymeleaf) 사용하기

Spring Boot에서 타임리프를 사용하기 위해 타임리프가 무엇인지, 그리고 기본적으로 알아야 하는 타임리프의 속성이나 주요 식(expression)을 알아보자. 그리고 스프링 부트와 타임리프를 연동하려면 어떤 것을 해야 하는지에 알아보자.

 

 타임리프(thymeleaf) 란?

타임리프(Thymeleaf)는 템플릿 엔진이다. 타임리프는 웹을 염두하고 설계해서 HTML 템플릿을 만들 때 적합합니다. 또한 자바 스크립트와 CSS에 적합한 템플릿 도 만들 수 있습니다. 다음은 타임리프가 제공하는 문법을 사용해서 작성한 템플릿의 예시 입니다.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="utf-8">
    <title>메인</title>
</head>
<body>
    <th:block th:unless="${authInfo}">
    <p>환영합니다.</p>
    <p>
        <a href="" th:href="@{/register/step1}">[회원 가입하기]</a>
        <a href="" th:href="@{/login}">[로그인]</a>
    </p>
    </th:block>
    
    <th:block th:if="${authInfo}">
    <p><span th:text="${authInfo.name}"></span>님, 환영합니다.</p>
    <p>
        <a href="" th:href="@{/edit/changePassword}">[비밀번호 변경]</a>
        <a href="" th:href="@{/logout}">[로그아웃]</a>
    </p>
    </th:block>
</body>
</html>

th:text, th:if, th:href 등은 타임리프가 제공하는 속성입니다. ${식}이나 @{식}은 이 속성에서 사용할 수 있는 타임리프 식입니다. 타임리프는 몇 가지 종류의 식을 제공하는데, 이 식을 사용하여 태그 몸체에 원하는 값을 삽입할 수 있습니다.

<span th:text="${authInfo.name}">회원</span>

${authInfo.name} 식에 해당하는 값이 '토르'일 경우, 타임리프 템플릿 엔진은 <span> 태그의 몸체 내용을 다음과 같이 '토르'로 변경합니다.

<span>토르</span>

 

 타임리프의 주요 식 (expression)

타임리프는 크게 변수 식, 메시지 식, 링크 식의 세 가지 식과 선택 변수 식을 제공합니다.

  • 변수 식: ${OGNL}
  • 메시지 식: #{코드}
  • 링크 식: @{링크}
  • 선택 변수 식: *{OGNL}

변수 식OGNL(객체의 프로퍼티 경로)에 해당하는 변수를 값으로 사용합니다. 타임리프에는 템플릿을 변환할 때 필요한 데이터를 가진 컨텍스트가 존재하는데 변수명을 사용해서 이 컨텍스트에 보관된 객체에 접근합니다. 스프링에서는 컨트롤러에서 생성한 모델 속성 이름이 변수명이 됩니다. 다음 코드는 변수 식의 사용 예입니다.

<p>아이디: <span th:text="${member.id}">id</span></p>

메세지 식외부 메시지 자원에서 코드에서 해당하는 문자열을 읽어와 출력합니다. 지정한 경로에 위치한 프로퍼티 파일을 메시지 자원으로 사용합니다. 스프링MVC의 <spring:message>와 같이 MessageSource로부터 코드에 해당하는 메시지를 읽어옵니다. 다음은 메시지 사용 식의 사용 예입니다.

<title th:text="#{member.register}">title</title>

링크 식링크 문자열을 생성합니다. 링크 식이 절대 경로면 JSTL의 <c:url> 태그와 동일하게 웹 어플리케이션 컨텍스트 경로를 기준으로 링크를 생성합니다.

<a href="#" th:href="@{/members}">목록</a>

웹 어플리케이션 컨텍스트 경로가 /ap5-chapc라고 할 경우 위 코드 변호나 결과는 다음과 같습니다.

<a href="/sp5-chapc/members">목록</a>

링크의 일부를 식으로 변경하고 싶다면 경로에 {변수}를 사용할 수 있습니다. 다음은 경로에 변수를 사용한 예입니다.

<a href="#" th:href="@{/members/{memId}(memId=${memId})}">상세</a>

위 코드에서 링크 식의 {memId}는 경로 변수입니다. 경로 변수 memId에 넣을 값은 뒤에 붙인 괄호 안에 지정합니다. 위 코드에서 뒤에 붙인 (memId=#{mem.id})는 경로 변수 memId의 값으로 ${mem.id}를 사용한다는 것을 뜻합니다. mem.id의 값이 10이면 위 코드의 처리 결과는 다음과 같습니다.

<a href="/sp5-chapc/members/10">상세</a>

선택 변수식은 th:object 속성과 관련되어 있습니다. th:object 속성은 특정 객체를 선택하는데 선택 변수 식은 th:object로 선택한 객체를 기준으로 나머지 경로를 값으로 사용합니다. 예를 들어 아래 코드에서 *{name}은 <div> 태그의 th:object에서 선택한 member객체를 기준으로 name 경로를 선택합니다. 따라서 *{name}은 ${member.name}과 같은 경로가 됩니다.

<div th:object="${member}">
	<span th:text="*{name}">name</span>
</div>

타임리프는 문자열 연결, 수치 연산 등 다양한 식을 제공한다. 이들 식에 대한 자세한 내용은 타임리프 튜토리얼 사이트를 참고한다.

 

 타임리프가 제공하는 주요 속성

타임리프는 HTML 태그에서 사용할 수 있는 속성을 제공한다. 다음 두 속성은 태그의 몸체에 원하는 값을 출력합니다.

  • th:text : 식의 값을 태그 몸체로 출력한다. '<'나 '&'와 같은 HTML 특수 문자를 '&It;'과 '&amp;'와 같은 엔티티 형식으로 변환한다.
  • th:utext: 식의 값을 태그 몸체로 출력한다. '<'나 '&'와 같은 HTML 특수 문자를 그대로 출력한다.

예를 들어 다음 코드를 보면

<h2 th:text="#{member.info}">info</h2>

위 코드에서 이름이 member.info인 메시지 코드 값이 "회원 정보"라면 이 코드의 처리 결과는 다음과 같습니다.

<h2>회원 정보</h2>

th:href 속성은 <a>태그의 href 속성을 지정합니다.

<a href="#" th:href="@{/members/10}" th:text="${mem.email}">email</a>

th:action 속성과 th:value 속성은 폼에서 사용합니다. th:action 속성은 <form>태그의 action 속성 값을 치환하고 th:value 속성은 <input> 태그와 같은 폼 관련 태그의 value 속성을 지정한다. 다음은 사용 예입니다.

<form action="#" th:action="@{login}" th:object="${loginCommand}" method="post">
<p>
    <label for="email" th:text="#{email}">email</label>:<br>
    <input type="text" id="email" th:field="*{email}" />
    <span th:each="err : ${#fields.errors('email')}" th:text="${err}"></span>
</p>
...
<input type="submit"value="로그인" th:value="#{login.btn}">
</form>

반복 처리는 th:each 속성을 사용합니다. 다음은 사용 예입니다.

<tr th:each="mem : ${members}">
    <td th:text="${mem.id}">id</td>
    <td><a href="#" 
        th:href="@{/members/{memId}(memId=${mem.id})}"
        th:text="${mem.email}">email</a></td>
    <td th:text="${mem.name}">name</td>
    <td th:text="${#temporals.format(mem.registerDateTime, 'yyyy-MM-dd')}">dateTime</td>
</tr>

위 코드에서 th:each 속성은 members 변수에 담긴 개별 요서에 대해 <tr> 태그를 반복합니다. 이때 각 구성 요소에 접근할 때 사용할 변수로 mem을 사용합니다.자식 태그는 mem 변수를 이용해서 각 요소의 속성에 접근합니다.

 

 타임리프 식 객체

타임리프는 식에서 사용할 수 있는 객체를 제공합니다. 이 식 객체를 이용하면 문자열 처리나 날짜 형식 변환 등의 작업을 할 수 있습니다. "#객체명"을 사용해서 식 객체를 사용합니다. 다음은 dates 식 객체를 이용해서 Data 타입 변수 값을 형식에 맞게 출력하는 예입니다.

<span th:text=${#dates.format(date, 'yyyy-MM-dd')}">date</span>

각 식 객체는 기능이나 속성을 제공합니다. dates 식 객체의 경우 format을 비롯해 날짜 형식 포맷팅을 위한 다양한 기능을 제공합니다. 타임리프가 제공하는 주요 식 객체는 다음과 같습니다.

  • #strings: 문자열 비교, 문자열 추출 등 String 타입 위한 기능 제공
  • #numbers: 포맷팅 등 숫자 타입을 위한 기능 제공
  • #dates, #calendars: Date타입과 Calendar 타입을 위한 기능 제공
  • #lists, #sets, #maps: List, Set, Map 타입을 위한 기능 제공

각 식 객체가 제공하는 기능과 속성 목록은 타임리프 튜토리얼 문서를 참고합니다.

 

 스프링 부트와 타임리프 연동 설정

스프링 부트에서 타임리프를 연동하는 것은 매우 간단합니다. 다음과 같이 타임리프를 위한 starter 모듈을 의존으로 추가하면 끝이고 ViewResolver나 기타 설정은 필요없습니다. 아래는 gradle 기준 thymeleaf를 추가하는 방법입니다.

implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'

스프링 부트는 기본적으로 src/main/resources/templates 폴더에서 타임리프 템플릿 파일을 검색합니다. 따라서 이 폴더에 타임리프 템플릿 파일을 위치시킵니다.

마무리

그 외 타임리프를 더 자세히 공부하고 싶다면 아래 공식 타임리프 Document 사이트를 참고한다.
http://www.thymeleaf.org

 

Thymeleaf

Integrations galore Eclipse, IntelliJ IDEA, Spring, Play, even the up-and-coming Model-View-Controller API for Java EE 8. Write Thymeleaf in your favourite tools, using your favourite web-development framework. Check out our Ecosystem to see more integrati

www.thymeleaf.org

 

관련글

위 글은 스프링5 프로그래밍 입문 (저자: 최범균) 책을 공부하면서 작성한 글입니다. (링크)

 

 
 

 

 

반응형