이번 포스트에서는 Thymeleaf에서 페이지의 레이아웃을 재사용하기 위한 thymeleaf-layout-dialect에 대해 살펴보자.
레이아웃 재사용
웹 페이지 레이아웃의 특징
Thymeleaf에서는 th:fragment, th:insert, th:replace를 이용해서 페이지마다 반복되는 뷰 부분(fragment)을 모듈화 하고 재사용할 수 있었다. 웹 페이지를 작성하다 보면 이런 fragment 만 복되드는 것이 아니라 레이아웃도 반복되는 것을 쉽게 알 수 있다.
위 그림을 보면 regist.html과 modify.html은 header+footer fragment에 각각의 content가 들어간 것을 알 수 있다. detail.html과 manage.html은 base-layout에 추가로 control을 위한 fragment가 추가된 레이아웃이다.
이런 layout을 재사용하기 위해서는 thymeleaf-layout-dialect라는 라이브러리를 사용할 수 있다.
페이지의 틀 역할을 하는 layout에서는 fragment들을 사용하고 content가 들어올 자리를 표시해주면 된다.
이를 위해 먼저 xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" 를 추가해야 한다. fragment를 사용하기 위한 th:replace, th:insert의 사용은 동일하다. 마지막으로 페이지마다 달라지는 content를 받아들이기 위해서 layout:fragment 를 사용하면 된다. header fragment에 전달될 값은 이 layout이 사용될 때 전달될 내용이므로 변수로 처리해 주자.
<!DOCTYPE html>
<!-- th와 layout namespace 추가-->
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8" />
<!-- 페이지를 구성하는 추가요소들도 자유롭게 사용 가능-->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
rel="stylesheet" />
</head>
<body>
<!-- header fragment를 이용해서 basic layout 구성-->
<div th:replace="fragments/header :: header(${subtitle})"></div>
<!-- 각 페이지별로 달라지는 content가 표시될 영역-->
<div layout:fragment="content"></div>
<!-- footer fragment를 이용해서 basic layout 구성-->
<div th:replace="fragments/footer :: footer"></div>
</body>
</html>
content 작성
마지막으로 layout을 사용해보자. html 태그에서 layout:decorate를 통해 사용할 layout을 지정하고 필요한 파라미터를 전달한다.
그리고 layout에서 선언한 layout:fragment="content"를 채울 내용만 공급해주면 된다. 이 파일은 단순히 content를 공급하는 역할이므로 이외의 내용은 화면에 표시되지 않는다.
<!--uselayout.html-->
<!DOCTYPE html>
<!--layout:decorate로 layout을 사용하면서 파라미터 전달-->
<html
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/layout-basic(subtitle='게시글 추가')}"
>
<h1>이런건 안나오겠죠?</h1>
<!-- layout에서 선언한 layout:fragment='content'를 채울 내용 작성-->
<div layout:fragment="content">
<h1>layout: 고유의 내용</h1>
</div>
</html>