Web/Thymeleaf

[Thymeleaf] 05.레이아웃 재사용

  • -

이번 포스트에서는 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라는 라이브러리를 사용할 수 있다.

 

설치

thymeleaf-dialect-layout(https://ultraq.github.io/thymeleaf-layout-dialect/)은 maven 등을 이용해서 간단히 설치할 수 있다.

<dependency>
  <groupId>nz.net.ultraq.thymeleaf</groupId>
  <artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>

 

페이지 구성

 

기본 절차

thymeleaf-dialect-layout을 사용할 때는 다음의 과정을 거친다.

  • fragment를 작성한다.
  • fragment를 이용해서 layout을 작성한다.
  • layout에 content를 추가해서 페이지를 구성한다.

 

header와 footer, config fragment 작성

재사용되는 fragment의 작성방법은 기존과 동일하다. 하지만 여기서는 이런 fragment가 커질 것을 대비해서 fragment별로 html을 만들어보자.

<!--/fragments/header.html-->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<div th:fragment="header(mainTitle)">
    <h1 th:text="${mainTitle}">Welcome To Board App</h1>
    <hr>
</div>
</html>
<!--/fragments/footer.html-->
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<div th:fragment="footer">
    <hr>
    <p>since 2024</p>
</div>
</html>
<!--/fragments/config.html-->
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<th:block th:fragment="config">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
          rel="stylesheet">
</th:block>
</html>

 

 
 

layout 작성

페이지의 틀 역할을 하는 layout에서는 fragment들을 사용하고 content가 들어올 자리를 표시해주면 된다.

이를 위해 먼저 xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" 를 추가해야 한다. fragment를 사용하기 위한 th:replace, th:insert의 사용은 동일하다. 마지막으로 페이지 마다 달라지는 content를 받아들이기 위해서 layout:fragment 를 사용하면 된다. header fragment에 전달될 값인 mainTitle은 이 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" />
    <th:block th:replace="~{fragments/config::config}"></th:block>
    <title th:text="${headTitle}"></title>
</head>
<body>
<div th:replace="~{fragments/header :: header(${mainTitle})}"></div>
<!-- 각 페이지별로 달라지는 content가 표시될 영역-->
<div layout:fragment="content"></div>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>

 

content 작성

마지막으로 layout을 사용해보자. html 태그에서 layout:decorate를 통해 사용할 layout을 지정하고 필요한 파라미터를 전달한다. 

그리고 layout에서 선언한 layout:fragment="content"를 채울 내용만 공급해주면 된다.  이 파일은 단순히 content를 공급하는 역할이므로 이외의 내용은 화면에 표시되지 않는다.

<!--index.html-->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="~{layouts/layout-basic(mainTitle='Board App에 오신것을 환경합니다.', 
                                              headTitle='board app')}">

<body>
  <h1>어차피 content만 공급하는 용도니 이런건 안나오겠죠?</h1>
  <!-- layout에서 선언한 layout:fragment='content'를 채울 내용 작성-->
  <div layout:fragment="content" class="container">
      <h1>layout: 고유의 내용</h1>
  </div>
</body>
</html>

 

위 페이지의 실행 결과는 아래와 같다.

생긴건 이래도 ㅎ 동작만 확인하자.

'Web > Thymeleaf' 카테고리의 다른 글

[Thymeleaf] 06. inline style  (1) 2024.01.14
[Thymeleaf] 04. 레이아웃  (0) 2023.12.14
[Thymeleaf] 03. 제어문  (1) 2023.12.14
[Thymeleaf] 02. 표준 표현식  (0) 2023.12.10
[Thymeleaf] 01. Hello Thymeleaf  (0) 2023.12.09
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.