타임리프란?
- 타임리프는 SSR(Server Side Render)을 하는 템플릿 엔진으로 백엔드 서버에서 HTML을 동적으로 렌더링 한다.
- 순수 HTML을 최대한 유지하기 때문에 html을 서버를 거치지 않고 직접 열어도 내용을 확인할 수 있다(당연히 동적으로 렌더링되지 않음) => 이처럼 순수 html을 그대로 유지하면서 뷰 템플릿도 사용할 수 있는 특징을 내츄럴 템플릿이라고 함
- 스프링의 기능을 편리하게 사용할 수 있다.
- 보통 간단한 화면을 구현할 때 사용된다
- html 문서에 선언을 추가하여 사용할 수 있다
<html xmlns:"http://www.thymeleaf.org">
타임리프의 기본 표현식
1. 텍스트 출력
타임리프는 기본적으로 html 태그에 th: 로 시작되는 기능을 속성으로 추가하여 사용할 수 있다
텍스트 출력은 th:text 를 사용한다
<span th:text="${data}></span>
다음과 같은 경우 서버에서 넘어온 data의 값이 span태그 사이에 출력된다
태그 밖에서 텍스트를 출력하고 싶은 경우 [[...]]를 사용한다
[[${data}]]
다음과 같은 경우에도 서버에서 넘어온 data값이 출력된다
그리고 타임리프는 서버에서 넘어오는 값을 자동으로 escape처리 해준다
예를들어 <b> 태그를 사용했을 경우 <b> 로 전달된다
이를 적용시키고 싶지 않은 경우 th:utext 또는 [(....)]를 사용한다
=> 데이터값을 받아와도 태그로 동작하기 때문에 의도하지 않은 상황 발생 가능, 안쓰는게 좋다
2. SpringEL
SpringEL은 Spring express language로 타임리프 내에서 변수를 사용가능하게 해준다
위의 ${data} 처럼 사용한다
User userA = new User("userA", 10);
User userB = new User("userB", 20);
List<User> list = new ArrayList<>();
list.add(userA);
list.add(userB);
Map<String, User> map = new HashMap<>();
map.put("userA", userA);
map.put("userB", userB);
model.addAttribute("user", userA);
model.addAttribute("users", list);
model.addAttribute("userMap", map);
다음과 같이 서버에서 model에 값을 넣어서 넘겨준다 (userA의 경우 username과 age를 가진 object임)
Object
${user.username}
${user['username']}
${user.getUsername()}
List
${users[0].username}
${users[0]['username']}
${users[0].getUsername()}
Map
${userMap['userA'].username}
${userMap['userA']['username']}
${userMap['userA'].getUsername()}
지역변수
th:with로 변수 선언하면 선언한 태그 내에서만 사용되는 지역변수가 된다
<div th:with="hello=${data}">
<p>안녕하세요 <span th:text="${data.username}"></span>입니다</p>
</div>
3. 기본 객체
${#request} - 스프링 부트 3.0부터 제공하지 않는다.
${#response} - 스프링 부트 3.0부터 제공하지 않는다.
${#session} - 스프링 부트 3.0부터 제공하지 않는다.
${#servletContext} - 스프링 부트 3.0부터 제공하지 않는다.
${#locale}
파라미터 정보를 받아오려면 request.getParameter()로 접근해야하기 때문에 더 간단하게 접근할 수 있도록 편의 객체를 제공한다.
${param.paramData}
${session.sessionData}
${@helloBean.hello('Spring!')}
편의객체를 통해 파라미터 정보, 세션 정보를 쉽게 받아올 수 있고 @를 이용하여 스프링빈에 직접 접근도 가능하다
4. 유틸리티 객체
타임리프 공식문서 참고해서 사용하기
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#expression-utility-objects
Tutorial: Using Thymeleaf
1 Introducing Thymeleaf 1.1 What is Thymeleaf? Thymeleaf is a modern server-side Java template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text. The main goal of Thymeleaf is to provide a
www.thymeleaf.org
Tutorial: Using Thymeleaf
1 Introducing Thymeleaf 1.1 What is Thymeleaf? Thymeleaf is a modern server-side Java template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text. The main goal of Thymeleaf is to provide a
www.thymeleaf.org
공식문서에 명시되지 않은 자바8에서 나온 LocalDate 관련 유틸리티 객체 사용
<h1>LocalDateTime</h1>
<ul>
<li>default = <span th:text="${localDateTime}"></span></li>
<li>yyyy-MM-dd HH:mm:ss = <span th:text="${#temporals.format(localDateTime,'yyyy-MM-dd HH:mm:ss')}"></span></li>
</ul>
<h1>LocalDateTime - Utils</h1>
<ul>
<li>${#temporals.day(localDateTime)} = <span th:text="${#temporals.day(localDateTime)}"></span></li>
<li>${#temporals.month(localDateTime)} = <span th:text="${#temporals.month(localDateTime)}"></span></li>
<li>${#temporals.monthName(localDateTime)} = <span th:text="${#temporals.monthName(localDateTime)}"></span></li>
<li>${#temporals.monthNameShort(localDateTime)} = <span th:text="${#temporals.monthNameShort(localDateTime)}"></span></li>
<li>${#temporals.year(localDateTime)} = <span th:text="${#temporals.year(localDateTime)}"></span></li>
<li>${#temporals.dayOfWeek(localDateTime)} = <span th:text="${#temporals.dayOfWeek(localDateTime)}"></span></li>
<li>${#temporals.dayOfWeekName(localDateTime)} = <span th:text="${#temporals.dayOfWeekName(localDateTime)}"></span></li>
<li>${#temporals.dayOfWeekNameShort(localDateTime)} = <span th:text="${#temporals.dayOfWeekNameShort(localDateTime)}"></span></li>
<li>${#temporals.hour(localDateTime)} = <span th:text="${#temporals.hour(localDateTime)}"></span></li>
<li>${#temporals.minute(localDateTime)} = <span th:text="${#temporals.minute(localDateTime)}"></span></li>
<li>${#temporals.second(localDateTime)} = <span th:text="${#temporals.second(localDateTime)}"></span></li>
<li>${#temporals.nanosecond(localDateTime)} = <span th:text="${#temporals.nanosecond(localDateTime)}"></span></li>
</ul>
5. URL 링크
타임리프에서 url생성 시 @{...} 사용
<li><a th:href="@{/hello}">basic url</a></li>
<li><a th:href="@{/hello(param1=${param1}, param2=${param2})}">hello query param</a></li>
<li><a th:href="@{/hello/{param1}/{param2}(param1=${param1}, param2=${param2})}">path variable</a></li>
<li><a th:href="@{/hello/{param1}(param1=${param1}, param2=${param2})}">path variable + query parameter</a></li>
param1 = data1, param2 = data2 일때
@{/hello}
=> /hello
@{/hello(param1=${param1},param2=${param2})}
=> /hello?param1=data1¶m2=data2
경로 뒤 () 부분이 파라미터로 처리됨
@{/hello/{param1}/{param2}(param1=${param1}, param2=${param2})}
=> /hello/data1/data2
경로에 변수가 있으면 () 부분이 경로 변수로 처리됨
@{/hello/{param1}(param1=${param1}, param2=${param2})}
=> /hello/data1?param2=data2
경로에 있는 변수는 경로 변수로 처리되고 나머지는 쿼리파라미터로 처리됨
6. 리터럴
소스 코드상에 고정된 값
상수과 헷갈렸었는데 상수와 다름
리터럴은 진짜 말 그대로 값 자체이고 상수는 리터럴을 이용해서 초기화시킨 변하지 않는 값임
리터럴의 경우 무조건 ' ' 로 감싸주어야 하지만 공백이 없는 경우 그냥 써도 리터럴로 인식됨
공백이 포함된 경우 ' '로 감싸주어야 함
변수를 포함할 경우 'hello' + ${data} 와 같이 사용하거나, 리터럴 대체를 사용할 수 있음
리터럴 대체의 경우 |...|의 형식으로
|hello ${data}| 처럼 사용하면 하나의 리터럴로 인식됨
7. 연산
th:text 에 포함시 계산된 후 출력됨
<li>1 > 10 = <span th:text="1 > 10"></span></li>
<li>1 > 10 = <span th:text="1 gt 10"></span></li>
<li>1 > 10 = <span th:text="1 > 10"></span></li>
셋 다 동일한 비교연산
비교 연산 시 불리언으로 출력. html 엔티티를 사용할 수도 있음
( > (gt), < (lt), >= (ge), <= (le), ! (not), == (eq), != (neq, ne)) <- SpEL을 지원하기 때문에 &;를 붙이지 않고도 사용가능
<li>(10 % 2 == 0)? '짝수':'홀수' = <span th:text="(10 % 2 == 0)? '짝수':'홀수'"></span></li>
조건식
자바의 조건식과 유사함 10%2 == 0이 true면 짝수, false면 홀수 출력
<li>${data}?: '데이터가 없습니다.' = <span th:text="${data}?: '데이터가 없습니다.'"></span></li>
<li>${nullData}?: '데이터가 없습니다.' = <span th:text="${nullData}?: '데이터가 없습니다.'"></span></li>
Elvis 연산자 ?:
? 앞의 값이 null이 아닐 시 값만 출력함
? 앞이 null이면 Elvis연산자의 뒷 부분을 출력함
<li>${data}?: _ = <span th:text="${data}?: _">데이터가 없습니다.</span></li>
<li>${nullData}?: _ = <span th:text="${nullData}?: _">데이터가 없습니다.</span></li>
No-operation ?:_
? 앞의 값이 null이 아닐시 값만 출력함
null이면 th:text무시하고 원래대로 동작함
8. 속성
기본적으로는 속성앞에 th: 를 붙여서 지정할 경우 서버에서 렌더링이 될 때 기존속성을 대체하거나 없는 경우 생성한다
다음 방법은 기존 속성을 대체하지 않고 기존 값에 값을 추가해 준다
th:attrappend = "class=' large'"
=> class 속성 뒤에 ' large'를 붙인다
th:attrprepend = "class='large '"
=> class 속성 뒤에 'large '를 붙인다
th:classappend = "large"
=> class 속성 뒤에 붙인다. 띄어쓰기 안해줘도 알아서 띄어서 붙여준다
checkbox type의 경우 checked 속성이 포함 되어있기만 하면 체크되기에 불편하다
=> th:checked 를 이용해 true면 값포함 , false면 checked속성을 넣지 않음으로 체크 설정이 가능하다
9. 반복
자바의 for(String item : list){ } 와 비슷하게 th:each를 사용할 수 있다
<tr th:each="user : ${users}">
<td th:text="${user.username}">username</td>
<td th:text="${user.age}">0</td>
</tr>
${users} 순서대로 처음부터 끝까지 반복
userStat 이용시 다양한 정보 얻을 수 있음
userStat.index: 0부터 시작
userStat.count: 1부터 시작
userStat.size: 전체 사이즈
userStat.even, userStat.odd: 홀수 짝수 여부
userStat.first, userStat.last: 처음, 마지막 여부
userStat.current: 현재 객체
10. 조건부 평가
th:if , th:unless를 사용한다
조건이 맞지 않으면 조건문이 들어간 태그를 렌더링하지 않는다
th:case 의 경우 다음과 같이 사용한다
<span th:case="10">10살</span>
<span th:case="20">20살</span>
<span th:case="*">기타</span>
11. 주석
표준 html 주석
<!--
<span th:text="${data}">html data</span>
-->
타임리프가 렌더링하지 않는다
서버없이 열었을 때도 주석으로 동작한다
타임리프 파서 주석
<!--/* [[${data}]] */-->
<!--/*-->
<span th:text="${data}">html data</span>
<!--*/-->
타임리프의 주석이다 렌더링할때 주석부분을 없애서 전달한다
두번째 주석의 경우 서버 없이 열었을 때는 보인다
타임리프 프로토타입 주석
<!--/*/
<span th:text="${data}">html data</span>
/*/-->
html주석으로 처리되기 때문에 파일로 열었을때는 보이지 않지만 타임리프 렌더링을 거치면 보이게 된다
12. 블록
<th:block> </th:block>으로 사용한다
th: 태그를 html태그에 넣어서 사용하기 애매한 경우에 사용한다
참고한 강의
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2/
'Spring Boot > thymeleaf' 카테고리의 다른 글
타임리프 스프링 통합 (0) | 2023.10.31 |
---|---|
타임리프(thymeleaf) 템플릿조각 / 템플릿 레이아웃 (0) | 2023.10.31 |