타임리프란?
타임리프는 백엔드 서버에서 HTML 파일을 동적으로 렌더링하는 용도로 사용된다.
타임리프를 사용하면 작성한 파일은 HTML을 유지하기 때문에 파일을 직접 열어서도, 뷰 템플릿을 거치더라도 동적으로 변경된 결과를 확인할 수 있다.
타임리프 적용 방법
build.gradle 파일에서 타임리프 라이브러리 추가
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
}
타임리프 사용 선언
<html xmlns:th="http://www.thymeleaf.org">
텍스트 - text, utext
th:text ${data}
기본적인 데이터 출력
<span th:text="${data}">
[[${data}]]
태그 바깥에서 데이터를 출력
<span> [[${data}]] </span>
이스케이프
타임리프에서 th:text 나 [[${data}]]는 기본적으로 <> 태그를 문자로 인식하는 이스케이프를 제공한다.
언이스케이프
이스케이프를 사용하지 않는 방법은
- th:text -> th:utext
- [[...]] -> [(...)]
를 사용하면 된다. 이스케이프를 사용하지 않아서 HTML이 정상적으로 돌아가지 않을 수 도 있기에 필요한 경우에만 언이스케이프를 사용하자
변수 사용
기본적으로 변수는 ${...}를 사용한다.
Object
객체의 프로퍼티 접근
<span th:text="${user.username}"></span>
List
인덱스를 적어서 객체의 프로퍼티 접근
<span th:text="${users[0].username}"></span>
Map
Key값을 적어서 객체의 프로퍼티 접근
<span th:text="${usersMap['userA'].username}"></span>
지역변수 th:with
선언한 태그 안에서만 사용할 수 있다.
<div th:with="man=${users[0]}">
<p>그 사람의 이름은 : <span th:text="${man.username}"></span></p>
</div>
URL 링크
기본적으로 URL을 생성할 때는 @{...} 문법을 사용한다.
단순 URL
결과 링크 : /hello
<a th:href="@{/hello}">basic url</a>
쿼리 파라미터
()에 있는 부분이 쿼리 파라미터로 처리된다. 결과 링크 : /hello?p1=data1&p2=data2
<a th:href="@{/hello(p1=${data1}, p2=${data2})}">GO HELLO WORLD</a>
경로 변수
URL 경로에 ()가 있으면 경로 변수로 처리된다. 결과 링크 : /hello/data1/data2
<a th:href="@{/hello/{p1}/{p2}(p1=${data1}, p2=${data2})}">GO HELLO WORLD</a>
리터럴
리터럴은 소스코드상에 고정된 값을 의미
- 문자 : 'abcd'
- 숫자 : 1234
- 불린 : true, false
- null : null
문자 리터럴
문자는 반드시 '..' 작은 따옴표로 감싸야 한다. 단 공백 없이 이어진다면 작은 따옴표를 생략해도 된다.
<span th:text="'data =' + ${data}"></span>
리터럴 대체
기존 문자 리터럴처럼 불편하게 작은 따옴표를 처리하지 않아도 된다.
<span th:text="|data= ${data}|"></span>
연산
비교 연산, 조건식 다 자바와 같은 형태를 취한다.
No-Operation
조건 결과가 _인 경우 타임리프가 실행되지 않는 것처럼 동작한다.
data가 true면 data가 그대로 출력되고, false면 _에 해당하므로 기존 값이 출력된다.
<span th:text="${data}?: _">데이터가 없습니다.</span>
속성 값 설정
타임리프는 주로 th:xx 로 속성을 지정할 수 있다.
속성 설정
기존 속성을 대체한다. name이 userA에서 userB로 대체
<input type="text" name="userA" th:name="userB"/>
속성 추가
기존 속성에 값을 추가한다.
- th:attrappend : 속성 값의 뒤에 추가 / 결과 값 : textA
- th:attrprepend : 속성 값의 앞에 추가 / 결과 값 : Atext
- th:classappend : class 속성 값의 뒤에 띄어쓰기를 포함하여 추가 / 결과 값 : text A
<input type="text" class="text" th:attrappend="class='A'" />
반복문
반복은 th:each 문법을 사용한다. 반복할 수 있는 값을 넣어 반복문을 생성한다.
반복 기능
오른쪽에서 값을 하나씩 꺼내 왼쪽 변수에 담는다.
<tr th:each="user : ${users}">
<td th:text="${user.name}">username</td>
</tr>
반복 상태 유지
두번 째 파라미터를 통해 반복의 상태를 확인 할 수 있다. 생략이 가능하며 생략시 [변수명+Stat] 이다.
<tr th:each="user : ${users}">
index = <span th:text="${userStat.index}"></span>
count = <span th:text="${userStat.count}"></span>
</tr>
주석
표준 HTML 주석
<!-- DATA -->
타임리프가 렌더링하지 않고 그대로 내비두어 HTML 코드안에서 주석을 볼 수 있다.
<!--<span th:text="${data}">html data</span>-->
타임리프 파서 주석
<!--/* DATA */-->
렌더링시 주석 부분을 제거하여 HTML 코드안에서 주석을 볼 수 없다.
<!--/* [[${data}]] */-->
타임리프 프로토타입 주석
<!--/*/ DATA /*/-->
HTML 파일을 그대로 열면 주석처리, 타임리프를 통해 렌더링한 경우에는 주석처리 되지 않고 정상 렌더링이 된다.
<!--/*/ <span th:text="${data}">html data</span> /*/-->
템플릿
타임리프는 공통 영역을 만들어 주는 템플릿 조각과 레이아웃 기능을 지원한다.
템플릿 조각
th:fragment로 템플릿의 이름을 지정하고 값을 넣을 공간을 만들어둔다.
이후 Main에서는 적용 시킬 부분에 템플릿 변수를 지정한다.
footer.html
<body>
<footer th:fragment="copy">
푸터 자리 입니다.
</footer>
<footer th:fragment="copyParam (param1, param2)">
<p>파라미터 자리 입니다.</p>
<p th:text="${param1}"></p>
<p th:text="${param2}"></p>
</footer>
</body>
</html>
Main.html
<body>
<h1>부분 포함</h1>
<h2>부분 포함 insert</h2>
<div th:insert="~{template/fragment/footer :: copy}"></div>
<h2>부분 포함 replace</h2>
<div th:replace="~{template/fragment/footer :: copy}"></div>
<h2>부분 포함 단순 표현식</h2>
<div th:replace="template/fragment/footer :: copy"></div>
<h1>파라미터 사용</h1>
<div th:replace="~{template/fragment/footer :: copyParam ('데이터1', '데이터2')}"></div>
</body>
th:insert
th:insert 를 사용하면 현재 태그 내부에 추가한다.
<div th:insert="~{template/fragment/footer :: copy}"></div>
<h2>부분 포함 insert</h2>
<div>
<footer>
푸터 자리 입니다.
</footer>
</div>
th:replace
th:replace 를 사용하면 현재 태그를 대체한다, 파라미터를 전달해 동적으로 조각을 렌더링 할 수도 있다.
<div th:replace="~{template/fragment/footer :: copyParam ('데이터1', '데이터2')}"></div>
<h1>파라미터 사용</h1>
<footer>
<p>파라미터 자리 입니다.</p>
<p>데이터1</p>
<p>데이터2</p>
</footer>
입력 폼처리
th:object
커맨트 객체를 지정, *{....} 선택 변수라고 하며, th:object에서 지정한 객체에 바로 접근할 수 있다.
<div th:object="${data}">
<input type="text" th:field="${data.name}" />
<input type="text" th:field="*{name}" />
</div>
th:field
HTML 태그의 id, name, value 속성을 자동으로 처리해준다.
<input type="text" id="itemName" name="itemName" th:value="*{itemName}" />
<input type="text" th:field="*{itemName}" />
체크박스
기존 HTML에서는 체크 박스를 선택하지 않고 폼을 전송하면 null 데이터가 전송된다.
그렇기 때문에 체크 해제를 인식하기 위한 히든 필드가 필요하다.
<input type="hidden" name="_open" value="on"/>
와 같이 언더스코어(_)를 붙여서 전송하면 체크의 유무가 판단된다. 하지만 th:field를 사용하면 히든 필드 부분이 자동으로 생성된다.
멀티 체크박스
멀티 체크박스의 경우 체크박스의 id가 각각 모두 달라야 한다
#ids.prev(...), #ids.next(...)
동적으로 생성되는 id값을 지정해준다.
주로 id값을 맞추기 위해서 사용되며 해당 코드에서는 lable의 id값과 input의 id값을 맞추기 위해 사용하였다.
<div th:each="fruit : ${Fruits}" class="form-check form-check-inline">
<input type="checkbox" th:field="*{fruits}" th:value="${fruit.key}"/>
<label th:for="${#ids.prev('fruits')}" th:text="${fruits.name}">사과</label>
</div>
출처 : 인프런 - 스프링 MVC 2편 feat.김영한 쌤
'웹 개발' 카테고리의 다른 글
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 (2) | 2024.02.27 |
---|---|
스프링 DB 1편 - 데이터 접근 핵심 원리 (0) | 2024.02.24 |
스프링 MVC 1편 (0) | 2024.01.23 |
HTTP 웹 기본 지식 (1) | 2024.01.05 |
SPRING 핵심 원리 - 기본편 정리 (0) | 2023.12.22 |