타임리프는 기본적으로 HTML 테그의 속성에 기능을 정의해서 동작한다.
HTML의 콘텐츠에 데이터를 출력할 때는 다음과 같이 th:text
를 사용한다.
<span ht:text="${data}"></span>
HTML 테그의 속성이 아니라 HTML 콘텐츠 영역안에서 직접 데이터를 출력하고 싶으면 다음과 같이 [[...]]
를 사용하면 된다.
컨텐츠 안에서 직접 출력하기 = [[${data}]]
경로 : hello.thymeleaf.basic
package hello.thymeleafbasic.basic;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Slf4j
@Controller
@RequestMapping("/basic")
public class BasicController {
@GetMapping("text-basic")
public String textBasic(Model model){
model.addAttribute("data","Hello Spring!!");
return "basic/text-basic";
}
}
/resources/templates/basic/text-basic.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>컨텐츠에 데이터 출력하기</h1>
<ul>
<li>th:text 사용 <span th:text="${data}"></span></li>
<li>컨텐츠 안에서 직접 출력하기 = [[${data}]]</li>
</ul>
</body>
</html>
실행: http://location:8080/basic/text-basic
HTML문서는 <,> 같은특수문자를기반으로정의된다.
따라서뷰템플릿으로HTML화면을생성할 때는 출력하는 데이터에 이러한 특수 문자가 있는 것을 주의해서 사용해야 한다.
앞에서 만든 예제의 데이터를 다음과 같이 변경해서 실행해보자.
"Hello Spring!"
"Hello <b>Spring!</b>"
<b> 테그를 사용해서 Spring!이라는 단어가 진하게 나오도록 해보자.
웹 브라우저에서 실행결과를 보자.
웹 브라우저: Hello <b\>
Spring!</b\>
소스보기: Hello <b>Spring!</b>
개발자가 의도한 것은 <b\>
가 있으면 해당 부분을 강조하는 것이 목적이었다. 그런데 <b\>
테그가 그대로 나온다.
소스보기를 하면 <
부분이 <
로 변경된 것을 확인할 수 있다.
웹브라우저는 <
를HTML테그의시작으로인식한다.
따라서 <
를테그의시작이아니라문자로표현할수 있는 방법이 필요한데, 이것을 HTML 엔티티라 한다. 그리고 이렇게 HTML에서 사용하는 특수 문자를 HTML 엔티티로 변경하는 것을 이스케이프(escape)
라 한다.
그리고 타임리프가 제공하는 th:text
, [[...]]
는 기본적으로 이스케이스(escape)를 제공한다.
<
-> <
>
-> >
기타 수 많은 HTML 엔티티가 있다.
🤞 참고 )
HTML 엔티티와 관련해서 더 자세한 내용은 HTML 엔티티로 검색해보자.
이스케이프 기능을 사용하지 않으려면 어떻게 해야할까?
타임리프는 다음 두 기능을 제공한다.
th:text
-> th:utext
[[...]]
-> [(...)]
@GetMapping("/text-unescaped")
public String textUnescaped(Model model) {
model.addAttribute("data", "Hello <b>Spring!</b>");
return "basic/text-unescaped";
}
/resources/templates/basic/text-unescape.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>text vs utext</h1>
<ul>
<li>th:text = <span th:text="${data}"></span></li>
<li>th:utext = <span th:utext="${data}"></span></li>
</ul>
<h1><span th:inline="none">[[...]] vs [(...)]</span></h1>
<ul>
<li><span th:inline="none">[[...]] = </span>[[${data}]]</li>
<li><span th:inline="none">[(...)] = </span>[(${data})]</li>
</ul>
</body>
</html>
th:inline="none"
: 타임리프는 [[...]]
를 해석하기 때문에, 화면에 [[...]]
글자를 보여줄 수 없다. 이 테그 안에서는 타임리프가 해석하지 말라는 옵션이다.
실행 : http://localhost:8080/basic/text-unescaped
실행해보면 다음과 같이 정상 수행되는 것을 확인할 수 있다.
📍 주의!
실제 서비스를 개발하다 보면 escape를 사용하지 않아서 HTML이 정상 렌더링 되지 않는 수 많은 문제가 발생한다. escape를 기본으로 하고, 꼭 필요한 때만 unescape를 사용하자.