템플릿 엔진 중 서버 사이드 템플릿 엔진에 해당하는 Thymeleaf에 대해 알아보자.
대부분의 html 속성을 th:xxx 로 변경할 수 있다.
ex: th:text="${변수명}"
표현식
◦ 변수 표현식: ${...}
◦ 선택 변수 표현식: *{...}
◦ 메시지 표현식: #{...}
◦ 링크 URL 표현식: @{...}
◦ 조각 표현식: ~{...}
리터럴
◦ 텍스트: 'one text', 'Another one!',…
◦ 숫자: 0, 34, 3.0, 12.3,…
◦ 불린: true, false
◦ 널: null
◦ 리터럴 토큰: one, sometext, main,…
text opeation
◦ 문자열 연결 : +
◦ 문자 대체 : |The name is ${name}|
연산
◦ Binary : +, -, *, /, %
◦ 마이너스 : -
boolean 연산
◦ Binary : and, or
◦ 부정 : !, not
비교 연산
◦ 비교연산자 : >, <, >=, <= (gt, lt, ge, le)
◦ 균등연산자 : ==, != (eq, ne)
조건 연산
◦ if-then : (if) ? (then)
◦ if-then-else : (if) ? (then) : (else)
◦ Default : (value) ?: (defaultValue)
타임리프의 가장 기본기능인 텍스트를 출력하는 기능
타임리프는 기본적으로 HTML태그의 속성에 기능을 정의해서 동작한다.
HTML의 콘텐츠에 데이터를 출력할 때는 다음과 같이 th:text를 사용한다.
<span th:text="${data}">
HTML 콘텐츠 영역 안에 직접 데이터를 출력할 때는 [[...]]를 사용한다.
[[${data}]]
HTML 문서는 <,> 같은 특수 문자를 기반으로 정의된다. 따라서 뷰 템플릿으로 HTML 화면을 생성할 때는 출력하는 데이터에 이러한 특수 문자가 있는 것을 주의해서 사용해야 한다.
예를들어
"Hello <b>Spring!</b>"
Spring을 강조하고 싶어서 태그를 추가하면 화면에서 속성이 적용되는 것이 아니라 태그가 포함된 문자열이 그대로 출력된다. 소스 보기를 하면
Hello <b>Spring!</b>
<
부분이<
로 변경된 것을 확인할 수 있다.
웹브라우저는 <
를 HTML 태그의 시작으로 인식하므로, 이를 문자로 표현할 수 있는 방법이 필요한데, 이것을 HTML 엔티티라고 한다.
<
-><
>
->>
이 외에도 수많은 HTML 엔티티가 있다.
그럼 이스케이프 기능을 사용하지 않으려면 어떻게 해야할까?
타임리프는 다음 두 기능을 제공한다.
th:text
->th:utext
[[...]]
->[(...)]
<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>
th:inline="none"
: 타임리프는 [[...]]
를 해석하기 때문에, 화면에 [[...]]
글자를 보여줄 수 없다. 이 태그 안에서는 타임리프가 해석하지 말라는 옵션이다.
이 옵션을 추가하면 Hello <b>Spring!</b>
을 출력했을 때 웹 브라우저에서 의도된 대로 수행된다.
Hello Spring!
하지만 실제 서비스를 개발할 때 escape를 사용하지 않아서 HTML이 정상 렌더링 되지 않는 문제가 발생하기도 한다. 따라서 escape를 기본으로 사용하되, 꼭 필요한 때에만 unescape를 사용하는 것이 좋다.
: 스프링이 제공하는 변수 표현식
<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>
Object
List
Map
th:with
를 사용하면 지역 변수를 선언할 수 있으며 지역 변수는 선언한 태그 안에서만 사용할 수 있다.
<div th:with="first=${users[0]}"> <p>처음 사람의 이름은 <span th:text="${first.username}"></span></p> </div>
${#request}
- 스프링부트 3.0부터 제공 X${#response}
- 스프링부트 3.0부터 제공 X${#session}
- 스프링부트 3.0부터 제공 X${#servletContext}
- 스프링부트 3.0부터 제공 X${#locale}
스프링 부트 3.0에서 위의 객체를 사용하려면 직접 model에 해당 객체를 추가해서 사용해야 한다.
참고자료
- 인프런 강의_김영한님의 <스프링 MVC 2편 - 백엔드 웹 개발 활용 기술>