본문 바로가기
IT/Template Engine

타임리프 레이아웃 (thymeleaf layout dialect)

by sgoho01 2019. 11. 20.

스프링부트 템플릿 엔진중 타임리프를 사용하여 간단한 테스트 페이지를 만들던 도중
공통으로 사용되는 페이지의 레이아웃을 적용시켜보려 검색하다 thymeleaf layout dialect라는 것을
발견하여 사용해본 내용 정리.

타임리프 레이아웃을 사용하기 위해서는 아래 2개의 의존성을 주입받아야 한다.
(현재 springboot를 사용하여 버전을 따로 명시 X)

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

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

 

thymeleaf-layout-dialect 의존성을 주입받으면서 실행하니 groovy에 대한 WAWARNING이 계속해서 출력된다.
해당 문제를 구글링해보니 대략적인 내용으로 thymeleaf-layout-dialect 라이브러리는 groovy를 참조하고 있는데
해당 부분에서 병목현상이 생기며 성능저하가 나타난다고 한다.

마침 thymeleaf-layout-dialect의 groovy를 제거한 버전이 있어서 해당 버전으로 교체하였다. 해당 라이브러리는 스프링부트에서 버전관리를 하지 않으므로 버전을 따로 명시해줘야 한다.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

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

<dependency>
  <groupId>com.github.zhanhb</groupId>
  <artifactId>thymeleaf-layout-dialect</artifactId>
  <version>2.4.1</version>
</dependency>

 

테스트 페이지는 부트스트랩의 무료템플릿 sb-admin-2를 이용하여 UI를 구성하였다.

전체 페이지 구성에서 가운데 표시한 부분만 메뉴마다 변경되므로 해당 화면 외의 페이지를 레이아웃으로 나눌것이다.

우선 크게 4부분으로 나누었다.

sideBar - 좌측 메뉴탭
topBar - 상단탭
content - 본문탭
footer - 하단탭

(추가로 head부분과 script부분도 나누었다.)

디렉토리의 구조는 다음과 같다.

| templates
|    ├  fragments
|    │         ├  footer.html  (하단탭)
|    │         ├  head.html  (헤더)
|    │         ├  script.html  (스크립트)
|    │         ├  sidebar.html  (좌측탭)
|    │         └  topbar.html  (상단탭)
|    ├  layout
|    │        └  default.html  (기본 레이아웃탭)
|    └  board.html  (본문탭)

 


<!DOCTYPE html>
<html lagn="ko" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">

    <!-- 공통 헤더-->
    <th:block th:replace="fragments/head :: headFragment"></th:block>

    <body id="page-top">
        <div id="wrapper">
            <!-- 사이드바-->
            <th:block th:replace="fragments/sidebar :: sidebarFragment"></th:block>

            <div id="content-wrapper" class="d-flex flex-column">
                <div id="content">
                    <!-- 상단바-->
                    <th:block th:replace="fragments/topbar :: topbarFragment"></th:block>
                    <!-- 본문-->
                    <th:block layout:fragment="content"></th:block>
                </div>
                <!-- 공통 하단-->
                <th:block th:replace="fragments/footer :: footerFragment"></th:block>
            </div>
        </div>

        <!-- 공통 스크립트-->
        <th:block th:replace="fragments/script :: scriptFragment"></th:block>
    </body>
</html>

<default.html>
레이아웃의 전체적인 틀을 작성한 코드이다. 
상단에 xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"으로 해당 파일이 기본 레이아웃임을 선언 후
아래 th:replace와 layout:fragment로 각 레이아웃의 코드를 불러올수 있다.

5라인의 th:replace 는 해당 부분에 <파일 경로 :: Fragment명>이라고 작성하면 해당 Fragment의 내용을
위치하겠다는 옵션이다. Fragment 명을 지정하는 방법은 th:fragment 옵션인데 아래 다른 레이아웃에서 작성하였다.

17라인의 layout:fragment는 해당 위치에 content라는 레이아웃의 코드를 불러온다는 의미이다.

 

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<th:block th:fragment="footerFragment">
    <footer class="sticky-footer bg-white">
        <div class="container my-auto">
            <div class="copyright text-center my-auto">
                <span>Copyright &copy; song gunho 2019</span>
            </div>
        </div>
    </footer>
</th:block>
</html>

<footer.html>
하단에서 공통으로 사용할 코드를 작성한 레이아웃이다.

th:fragment 옵션으로 아래 코드의 Fragment의 이름을 선언해주고 공통 레이아웃에서 해당 Fragment명을 호출하여 해당 코드를 불러올수 있다.

default.html에서 th:replace="fragments/footer :: footerFragment"가 footer.html의 파일 경로, Fragment명을 호출하여 레이아웃을 구성할수 있다. 

<!DOCTYPE html>
<html lagn="ko" xmlns:th="http://www.thymeleaf.org">
<th:block th:fragment="headFragment">
    <head>
        <meta charset="UTF-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

        <title>타이틀</title>

	<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
        <link th:href="@{/vendor/fontawesome-free/css/all.min.css}" rel="stylesheet" type="text/css">
        <link th:href="@{/css/sb-admin-2.min.css}" rel="stylesheet">

        <!-- DataTable -->
        <link th:href="@{/vendor/datatables/dataTables.bootstrap4.css}" rel="stylesheet">

    </head>
</th:block>
</html>

<head.html>
헤더 레이아웃에서는 공통으로 사용할 css를 선언해주었다.

<!DOCTYPE html>
<html lagn="ko" xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">

<!-- 공통으로 쓰이는 script파일을넣는다.-->
<th:block th:fragment="scriptFragment">


    <!-- Bootstrap core JavaScript-->
    <script th:src="@{/vendor/jquery/jquery.min.js}"></script>
    <script th:src="@{/vendor/bootstrap/js/bootstrap.bundle.min.js}"></script>

    <!-- Core plugin JavaScript-->
    <script th:src="@{/vendor/jquery-easing/jquery.easing.min.js}"></script>

    <!-- Custom scripts for all pages-->
    <script th:src="@{/js/sb-admin-2.min.js}"></script>

    <!-- Page level plugins -->
    <script th:src="@{/vendor/chart.js/Chart.min.js}"></script>

    <!--  DataTable  -->
    <script th:src="@{/vendor/datatables/jquery.dataTables.js}"></script>
    <script th:src="@{/vendor/datatables/dataTables.bootstrap4.js}"></script>

    <!-- Page level custom scripts -->
    <!--    <script th:src="@{/js/demo/chart-area-demo.js}"></script>-->
    <!--    <script th:src="@{/js/demo/chart-pie-demo.js}"></script>-->

</th:block>
</html>

<script.html>
스크립트 레이아웃에선 공통으로 사용하는 스크립트를 선언해주었다.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">

<th:block th:fragment="sidebarFragment">

    <!-- Sidebar -->
    <ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
        ...
    </ul>
    <!-- End of Sidebar -->

</th:block>

</html>

<sidebar.html>
좌측 메뉴의 코드

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml">

<th:block th:fragment="topbarFragment">

    <!-- Topbar -->
    <nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
        ...
    </nav>
    <!-- End of Topbar -->

</th:block>
</html>

<topbar.html>
상단 탭 코드

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorator="layout/default">

<th:block layout:fragment="content">
    <!-- Begin Page Content -->
    <div class="container-fluid">
        ..
    </div>
</th:block>
</html>

<board.html>
본문 코드가 위치하는 파일로서 상단에 layout:decorator="layout/default"을 선언하여 기본 레이아웃 파일을 사용하겠다라는 의미이다.

board.html의 layout:fragment="content" 아래의 코드는 기본 레이아웃의 content라는 부분에 위치한다.

해당 파일을 불러오면 layout/default의 기본 레이아웃 소스를 읽어 온 후 default.html의 layout:fragment="content" 부분에 위 board.html의 코드를 넣어 화면을 불러온다.

 

댓글