타임리프(Thymeleaf)란?
- 타임리프는 백엔드 서버에서 HTML을 동적으로 렌더링 하는 용도로 사용되는 템플릿 엔진이다.
( 백엔드 서버에서 동적으로 렌더링 한다는 말은 타임 리프가 서버 사이드 HTML 렌더링(SSR) 중 하나라는 걸 뜻한다. )
SSR에는 타임리프를 제외하고, JSP, FreeMarker, Velocity 등이 있는데, 스프링을 사용하는 한, 스프링을 통합 지원해주는 타임리프가 1순위라고 생각한다.
타임리프(Thymeleaf)의 특징
- 서버 사이드 HTML 렌더링(SSR)
- 네츄럴 템플릿
- 스프링 통합 지원
여기서 네츄럴 템플릿이란?
순수 HTML을 최대한 유지하려는 타임리프의 특징이다.
타임리프로 작성한 파일은 HTML을 유지하기 때문에 웹 브라우저에서 파일을 직접 열어도 내용을 확인할 수 있고, 서버를 통해 뷰 템플릿을 거치면 동적으로 변경된 결과를 확인할 수 있다.
→ 이렇게 순수 HTML을 그대로 유지하면서 뷰 템플릿도 사용할 수 있는 타임리프의 특징을 네츄럴 템플릿이라고 한다.
타임리프를 사용하려면?
해당 프로젝트를 생성할 때 Gradle에 Thymeleaf를 추가해주야 한다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-tymeleaf'
...
}
build.gradle에 위와 같이 선언되어 있나 확인해보도록 하자.
또한,
타임리프를 사용할 HTML 파일에서 타임리프 사용 선언을 해주어야 한다.
<html> 부분을 아래와 같이 바꿔주면 끝이다.
<html xmlns:th="http://www.thymeleaf.org">
타임리프 기본 표현식
기본 표현식들은 위의 사진과 같은데, 더 자세하고 많은 내용은 아래 차차 풀어보겠다.
텍스트 - text, utext
텍스트를 출력하는 기능
타임리프는 기본적으로 HTML 테그의 속성에 기능을 정의해서 동작한다.
때문에, HTML의 컨텐츠에 데이터를 출력할 때는 아래의 형식을 따르면 된다.
<span th:text = "${data}">
해당 테그를 사용하지 않고 HTML 컨텐츠 영역 안에서 직접 데이터를 출력하고 싶다면, 아래와 같은 형식을 따라보자.
컨텐츠 안에서 직접 출력하기 = [[${data}]]
여기서 data는 컨트롤러에서 model에 담아 넘겨주는 데이터의 이름이다.
Ex)
<h1>컨텐츠에 데이터 출력하기</h1>
<ul>
<li>th:text 사용 <span th:text="${data}"></span></li>
<li>컨텐츠 안에서 직접 출력하기 = [[${data}]]</li>
</ul>
Escape
HTML 문서는 <, > 와 같은 특수 문자를 기반으로 정의된다. 따라서 뷰 템플릿으로 HTML 화면을 생성할 때는 이러한 특수 문자를 주의해야 한다.
만약에 위의 예시에 data 값으로 "Hello <b>Spring!</b>" 를 넘긴다면 어떻게 될까?
여기서 <b>테그를 사용함으로써, Spring! 단어를 진하게 나오도록 하고 싶은 것이다.
→ 웹 브라우저에서 실행 결과를 보면,
Hello <b>Spring!</b>
이렇게 나온다.
<와 /> 부분이 다 바뀐 것이다.
HTML 엔티티
웹 브라우저는 < 를 HTML 테그의 시작으로 인식한다. 따라서 < 를 문자로 표현할 방법이 필요한데, 이것을 HTML 엔티티라고 한다. 이렇게 HTML에서 사용하는 특수 문자를 HTML 엔티티로 변경하는 것을 이스케이프(escape)라고 한다.
( 위에서 설명한 th:text, [[...]] 형식은 기본적으로 escape를 지원함 )
만약 위에 나의 바램처럼 이스케이프를 사용하지 않고, <b>테그를 적용시키려면 어떻게 해야 할까?
Unescape
타임리프는 다음 두 기능을 제공한다.
- th:text → th:utext
- [[...]] → [(...)]
Ex)
<li>th:utext = <span th:utext="${data}"></span></li>
<li><span th:inline="none">[(...)] = </span>[(${data})]</li>
th:inline="none" : 타임리프는 [[...]] 를 해석하기 때문에, 화면에 [[...]] 글자를 보여줄 수 없다.
이 테그 안에서는 타임리프가 해석하지 말라는 옵션이다.
해당 형식들을 사용하면 이스케이프 기능을 사용하지 않을 수 있고, <b>테그를 사용할 수 있다.
하지만 실무에서는 escape 기능은 거의 사용한다고 볼 수 있다. 왜냐하면, 사용자들이 여러 특수 문자들을 많이 기입하고 하기 때문에 에러가 발생할 수 있기 때문이다.
이스케이프 기능을 사용하는게 기본! 필요시에만 Unescape!
변수 - SpringEL
타임리프에서 변수를 사용할 때에는 아래의 변수 표현식을 사용한다.
${...}
해당 표현식에는 스프링 EL이라는 스프링이 제공하는 표현식을 사용할 수 있다.
User이라는 class를 만들고, username, age를 통해 생성자를 만들어 준다.
List<User>, Map<String,User> 등에 userA, userB를 만들어서 넣어주고, 이를 model에 담아서 넘겨준다.
HTML 파일
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>SpringEL 표현식</h1>
<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>
</body>
</html>
Object, List, Map에 따른 다양한 표현식을 사용했다.
자바빈 프로퍼티 접근법을 사용한다.
전부, userA라는 것을 출력하게끔 만들었다.
Object는 간단하게 프로퍼티 접근으로 user.username을 사용했다. 이는, user.getUsername() 메서드와 같다고 보면 된다.
List에서는 users[index].username 등을 사용해 index를 기입하여 그 값을 추출했다.
Map에서는 userMap['key'].username 등을 사용해 맵의 key값을 넣어 그 값을 추출했다.
지역 변수 선언
자바와 같이 지역 변수를 선언해서 사용할 수도 있다.
th:with 을 사용하면 지역 변수를 선언해서 사용할 수 있다. 해당 지역 변수는 선언한 테그 내에서만 사용이 가능.
<h1>지역 변수 - (th:with)</h1>
<div th:with="first=${users[0]}">
<p>처음 사람의 이름은 <span th:text="${first.username}"></span></p>
</div>
코드를 보면, th:with 으로 시작했고, first 변수에 users List의 첫번째 user 객체를 할당했다.
그리고 first.username을 통해 userA 라는 값이 출력된다.
→ 출력 결과 : 처음 사람의 이름은 userA
first라는 변수는 <div> </div> 테그 내에서만 사용이 가능하다.
다음 게시글
글의 분량을 나누기 위해 해당 게시글은 여기까지.. 다음 게시글에 타임 리프에 더 자세한 내용들을 적도록 하겠다.
예를 들어, 타임리프에서 Http 요청 파라미터에 접근, Http 세션에 접근 등과 타임리프의 유틸리티 객체들 등을 말하고 타임리프에서 URL 링크를 어떻게 처리하는지 등을 설명하겠다.
'SSR(Server Side Rendering) > Thymeleaf' 카테고리의 다른 글
Thymeleaf와 Spring Form(체크 박스, 라디오 버튼, 셀렉트 박스) (0) | 2023.12.13 |
---|---|
Thymeleaf(타임리프) 기능(주석, 블록, 자바스크립트 인라인, 템플릿 조각, 템플릿 레이아웃) (0) | 2023.12.12 |
Thymeleaf(타임리프) 기본 기능 및 객체, 문법(리터럴 대체, 반복, 조건) (0) | 2023.12.12 |