이번 포스트에서는 Thymeleaf에서의 layout 작성 방법에 대해 알아보자.
Thymeleaf 레이아웃
th:fragment
일반적으로 웹 페이지들은 header, footer 등 반복적으로 등장하는 요소들을 가지며 이들을 매번 만들지 않고 fragment 같은 조각으로 만들어 놓고 재사용 한다. 이를 위해 Thymeleaf에서는 th:fragment를 사용한다. /src/main/resources/fragments 아래처럼 header.html과 footer.html을 만들어보자.
header를 구성할 때는 각 페이지의 부제목(subtitle)을 파라미터로 전달받아서 사용하기 위해 header(subtitle)의 형태를 사용할 수 있다.
<!--header.html-->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<!-- 사용처별로 달라질 내용은 파라미터로 선언 가능-->
<th:block th:fragment="header(subtitle)">
<h1>Welcome To Thymeleaf Test Page</h1>
<hr />
<!-- 파라미터로 전달받은 내용 사용 가능-->
<h2 th:text="${subtitle}">부제목</h2>
</th:block>
</html>
사실 th:fragment에서 변수를 선언하지 않아도 동작한다. 하지만 subtitle에 어떤 값이 할당되어야 하는가를 명확히 이해하기 위해서는 변수를 선언하는 것이 좋겠다.
<!-- footer.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div th:fragment="footer">
<hr />
<p>since 2007</p>
</div>
</html>
물론 header.html과 footer.html을 하나의 html에 만들어도 상관없지만 내용이 커질 수 있으므로 분리하는 것이 좋다.
th:insert와 th:replace
header.html이나 footer.html은 단독적으로 사용되지 않고 th:fragment 단위로 조각조각 분리되서 활용된다. 이때 file의 이름은 templatename이 되고 header, footer는 selector가 된다.
fragment를 가져와서 사용할 때는 th:insert와 th:replace를 사용한다. 두 속성 모두 사용법은 유사한데 ~{templatename::selector} 형태로 사용한다. 차이점은 단어 그대로 insert는 fragment를 삽입하는 형태이고 replace는 대체한다.
즉 아래와 같이 fragment를 사용할 때
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Title Here</title>
</head>
<body>
<div th:insert="~{fragments/header::header(subtitle='Thymeleaf 활용')}"></div>
<h1>고유의 내용</h1>
<span th:replace="~{fragments/footer::footer}"></span>
</body>
</html>
fragment에 선언된 파라미터를 사용하기 위해서는 fragemtn 호출 시 () 안에 paramname=value 형식으로 값을 넣어주면 된다.
생성되는 html을 살펴보면 th:insert는 내부에 추가되므로 div>div의 구조가 되고 replace는 대체되므로 span이 div로 변경되어있음을 알 수 있다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Title Here</title>
</head>
<body>
<div>
<h1>Welcome To Thymeleaf Test Page</h1>
<hr />
<!-- 파라미터로 전달받은 내용 사용 가능-->
<h2>Thymeleaf 활용</h2>
</div>
<h1>고유의 내용</h1>
<div>
<hr />
<p>since 2007</p>
</div>
</body>
</html>