본문 바로가기
📌 Back End/└ Spring

[Spring] Thymeleaf(타임리프)란? (+기본적인 사용법)

by 쫄리_ 2023. 3. 16.
728x90
반응형

타임리프(Thymeleaf) 란?

타임리프는 컨트롤러가 전달하는 데이터를 이용해 동적으로 화면을 만들어주는 역할을 하는 뷰 템플릿 엔진이다. 

타임리프가 갖는 대표적인  특징은 다음과 같다.

 

  • 서버상에서 동작하지 않아도 HTML 파일의 내용을 바로 확인이 가능하다.
  • 순수 HTML 구조를 유지한다.

타임리프(Thymeleaf) 사용

1) 라이브러리 추가

Gradle - build.gradle

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

 

Maven - pom.xml

<dependency> 
	<groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

 

2) 기본 경로

타임리프는 다음과 같이 기본 뷰 템플릿 경로로 다음과 같이 아래 코드가 자동으로 추가된다.

spring.thymeleaf.prefix=classpath:/templates/ 
spring.thymeleaf.suffix=.html

 

즉, 컨트롤러에서 String으로 반환을 하게 되면 기본 경로 패스가 붙게 된다.

/templates/response/hello.html

@Controller 
public class ResponseViewController {

    @RequestMapping("/response-view-v2") 
    public String responseViewV2(Model model) {
    model.addAttribute("data", "hello!!"); 
    
    return "response/hello"; 
    } 
}

 

3) 템플릿 사용 파일 위치 (HTML)

스프링부트에서는 템플릿용 파일의 기본 경로가 미리 지정되어 있습니다.
src/main/resources/templates 안에 꼭 html 파일을 만드세요.

 


타임리프(Thymeleaf) 기본 표현식

타임리프를 사용하기 위해서는 html 태그에 다음과 같이 추가해준다.

대부분의 HTML 속성은 타임리프의 속성으로 쓰이는 th:html 속성으로 변경할 수 있다.

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

 

  • 변수 : ${...}   ${student.id}
  • 선택자 : *{...}   *{id}
  • 메시지 : #{...}   #{id}
  • 링크URL : @{...}   @{https://www.naver.com}
  • 부분적 표현 : ~{...}
  • 조건 연산자 : and, or, not, !
    • ${student.age} > 20 and ${student.age} < 10  각각 분리하여서 사용하거나
    • ${student.age > 20 or student.age < 10}  한 번에 묶어서 사용하는 것도 가능
  • 텍스트 결합 : ${student.id}+${student.name}
  • 문장 결합 : |학생 아이디 : ${student.id}, 학생 이름 : ${student.name} |  로 전체 문장을 묶어줌
  • if-then : if ? then  ${student.age < 20} ? '청소년'
  • if-then-else : if ? then : else   ${student.age < 20} ? '청소년' : '성인'
  • default : value ?: defaultValue

@{ URL 링크 } - URL 링크 표현식

  • @{ URL 링크 } : 타임리프는 URL 링크를 사용하는 경우 @{...}를 사용한다.
  • URL 링크 표현식을 사용하면 서블릿 컨텍스트가 자동으로 포함이 된다.

사용예시

/* 예시 1 */ 
th:href="@{/css/bootstrap.min.css}"

/* 예시 2 */
th:href="@{/basic/items/{itemId}(itemId=${item.id}, query='test')}"

/* 예시 3 */
리터럴 대체 문법을 사용해서 더 간단히 할 수 있다.
th:href="@{|/basic/items/${item.id}|}"

 

[Controller]

 

[Html - index.html]

@{/link}로 link.html 페이지로 이동하게 지정

 

[Html - link.html]

 

[결과]


리터럴 | - 리터럴 대체

  • 타임리프에서 문자와 표현식 등은 분리되어 있기 때문에 더해서 사용해야 한다.
  • 리터럴 대체 문법을 사용하면, 더하기 없이 편리하게 사용할 수 있다.

사용예시

/* 예시 1 */
<span th:text="'welcome to our application, ' + ${user.name} + '!' ">
<span th:text="|welcome to our application, ${user.name}!|">

/* 예시 2 */
th:onclick="'location.href=' + '\'' + @{/basic/items/add} + '\''"
th:onclick="|location.href='@{/basic/items/add}'|"

${ 변수명 } - 변수 표현식

  • 모델에 포함된 값이나, 타임리프 변수로 선언한 값을 조회할 수 있다.
  • 프로퍼티 접근법을 사용 ( item.getPrice()  →  item.price )

사용예시

<td th:text="${item.price}">10000</td> ( 10000 대신 item.price 값이 들어간다. )

 

[Controller]

Model을 이용해 testSTR이란 변수로 메시지를 전달합니다.

 

[Html]

${변수}로 Controller에서 Model로 보낸 데이터를 받습니다.

 

[결과]


*{ 변수명 } - 객체 변수 선택자

  • th:object 태그를 통해서 변수 ${ }로 객체를 받고
    객체의 변숫값을 "*{ }"로 받습니다.

사용예시

[Controller]

Member 객체에 값을 넣고 member.html로 객체를 model을 통해 전달합니다.

 

[Data 객체 - Member.java]

Member 객체에 no, name, phone 변수를 지정했습니다.

 

[Html]

th:object 태그를 통해서 변수 ${ }로 객체를 받고 객체의 변숫값을 "*{ }"로 받습니다.

 

[결과]


#{ 변수명 } - 외부 자원 변수 표현식

  • 메시지, properties와 같은 외부 자원의 데이터를 조회

사용예시

th:text="#{member.register}"

 


타임리프(Thymeleaf) 데이터 바인딩, 조건문, 반복문, 상태변수

 

  • 데이터 바인딩 : th:text, th:value, th:placeholder
  • 조건문 : th:if, th:unless
  • form : th:object
  • 반복문 : th:each
  • 상태변수 (index, count 등)

th:text, th:value, th:placeholder - 데이터 바인딩

p, span, div 등의 태그에서 데이터를 텍스트로 바인딩할 때 사용한다.
th:utext 라는 속성도 있는데, utext의 경우 
html 태그를 escape처리 하지 않기 때문에 보안에 취약해서 사용할 때 주의해야 한다.

 

사용예시

@RequestMapping("selectStudentInfo")
ModelAndView selectStudentInfo() {
    ModelAndView mav = new ModelAndView("/selectStudentInfo");
        
    Student student = new Student();
    student.setId("210000001");
    student.setName("Anne Marie");
    student.setAge(29);
        
    /** thymeleaf에서 사용할 object명, object를 ModelAndview에 넣어준다. */
    mav.addObject("student", student);
        
    return mav;
}
<p th:text="${student.id}"></p>		<!-- 210000001 -->
<input type="text" th:placeholder="${student.name}" /> <!-- Anne Marie -->
<p><span th:utext="${student.age}"></span></p>  <!-- 29 -->

th:if, th:unless - 조건문

조건문을 사용할 때 else 대신 unless를 사용한다. 
주의할 점은 if문의 조건식과 unless의 조건식을 동일하게 해주어야 한다.

 

사용예시

<p th:if="${student.grade > 80}">
  합격입니다!!!
</p>
<p th:unless="${student.grade > 80}">
  불합격.. 좀 더 노력하세요!
</p>

 

사용예시

[Html]

 

[결과]


th:object - form

form submit을 할 때, form의 데이터가 th:object에 설정해준 객체로 받아진다.

 

사용예시

@RequestMapping("selectStudentInfo")
ModelAndView selectStudentInfo() {
    ModelAndView mav = new ModelAndView("/selectStudentInfo");
        
    Student student = new Student("210000001", "Anne Marie", 29);
     
    List<Student> studentList = new ArrayList<>();
    studentList.add(student);
    studentList.add(new Student("210000002", "Lukas Graham", 33));
    studentList.add(new Student("210000003", "Christina Grimmie", 22));
  
    /** thymeleaf에서 사용할 object명, object를 ModelAndview에 넣어준다. */
    mav.addObject("studentList", studentList);
        
    return mav;
}

th:each - 반복,  index, count - 상태변수

리스트 객체를 반복할 때 사용한다.

 

사용예시

@RequestMapping("selectStudentInfo")
ModelAndView selectStudentInfo() {
    ModelAndView mav = new ModelAndView("/selectStudentInfo");
        
    Student student = new Student("210000001", "Anne Marie", 29);
     
    List<Student> studentList = new ArrayList<>();
    studentList.add(student);
    studentList.add(new Student("210000002", "Lukas Graham", 33));
    studentList.add(new Student("210000003", "Christina Grimmie", 22));
  
    /** thymeleaf에서 사용할 object명, object를 ModelAndview에 넣어준다. */
    mav.addObject("studentList", studentList);
        
    return mav;
}
<table>
  <tr th:each="student : ${studentList}">
    <td th:text="|${student.id} : ${student.name}|"></td>
    <td th:text="|나이: ${student.age}|"
  </tr>
</table>

<!-- /* 출력 결과 */ -->
210000001 : Anne Marie
나이: 29
210000002 : Lukas Graham
나이: 33
210000003 : Christina Grimmie
나이: 22

 

th:each를 사용할 때 기본적으로 status 변수를 제공해주고 이를 이용하여 index나 count 등의 값을 사용할 수 있다.

기본적으로 변수명Stat 로 사용할 수 있으며,

변수명을 다르게 사용하고 싶을 경우 직접 명시할 수 있다.

index의 경우 0부터 시작한다.

index : 현재 인덱스(0부터 시작)
count : 현재 인덱스(1부터 시작)
size : 전체 개수
current : 현재 요소
even : 현재 반복이 짝수인지(boolean)
odd : 현재 반복이 홀수인지(boolean)
first : 현재 반복이 첫번째인지(boolean)
last : 현재 반복이 마지막인지(boolean)
<!-- /* 상태변수명을 바꾸고 싶을 경우 직접 명시할 수 있다.
			<tr th:each="student, stat : ${studentList}"> */ -->
<div th:each="student : ${studentList}">
  <p th:text="${'index: ' + studentStat.index}"></p>
  <p th:text="${'count: ' + studentStat.count}"></p>
  <p th:text="${'size: ' + studentStat.size}"></p>    
  <p th:text="${'current: ' + studentStat.current}"></p>
  <p th:text="${'even: ' + studentStat.even}"></p>
  <p th:text="${'odd: ' + studentStat.odd}"></p>
  <p th:text="${'first: ' + studentStat.first}"></p>
  <p th:text="${'last: ' + studentStat.last}"></p>
</div>

 

사용예시

[Controller]

 

[Html]

 

[결과]


기타 문법, 타임리프 주석 사용법

  • 블록 태그 : th:block
  • 타임리프 주석 : <!-- /*  */ -->

th:block - 블록

th:if문을 사용하고 싶은데, html 태그는 사용하고 싶지 않거나 사용할 수 없는 경우라면? 

th:block을 사용하여 타임리프 문법을 사용할 수 있습니다.

 

사용예시

<th:block th:if="${student.grade < 60}" th:text="|${student.name} 불합격!|"></th:block>
<th:block th:if="${student.grade >= 60 and student.grade < 90}" th:text="|${student.name} 통과! B등급!!|"></th:block>
<th:block th:if="${student.grade >= 90}" th:text="|${student.name} 통과! A등급!!|"></th:block>

 


<!-- /*  */ --> - 주석

사용예시

<!-- /* 이렇게 하면 타임리프 파싱될 때 일반 html 주석이 아니라 타임리프 주석으로 처리되어 클라이언트에서 볼 수 없습니다. 소스보기에서 숨겨야 하는 주석일 경우 타임리프 주석으로 처리하면 됩니다. */ -->

 

 

728x90
반응형