[Spring Boot] Thymeleaf(타임리프) layout dialect 사용하기
웹 페이지를 만들게되면 기본적으로 head, header, content, footer 등의 레이아웃으로 나누어서 만들게된다. 기존에 스프링과 jsp를 통하여 만들 때 tiles를 이용하여 각 영역들을 분할하여 작업할 수 있었는데, 타임리프에선 thymeleaf-layout-dialect를 이용하여 비스하게 사용할 수 있다.
타임리프는 프로젝트를 생성할 때 의존성을 추가하면 된다.
2021.08.13 - [Spring-Boot] - [Spring Boot] 프로젝트 생성하기(Intellij)
기존에 프로젝트에 타임리프를 사용중이라면 의존성을 하나 더 추가하면 된다.
메이븐 사이트에 접속하여 "Thymeleaf layout dialect"를 검색한다.
Maven인지 Gradle인지는 각자 프로젝트 의존성 설정방식에 맞추면된다. 현재 프로젝트에서는 Gradle을 사용하고 있기때문에 Gradle을 사용한다.
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
// https://mvnrepository.com/artifact/nz.net.ultraq.thymeleaf/thymeleaf-layout-dialect
implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect', version: '2.5.3'
해당 코드를 Gradle 의존성에 추가했다면 하나의 웹페이지를 구성할 영역들과 동적으로 바꿀 페이지를 지정하면 된다.
- layout/head.html(영역으로 쓸 페이지)
- layout/header.html(영역으로 쓸 페이지)
- layout/navBar.html(영역으로 쓸 페이지)
- layout/footer.html(영역으로 쓸 페이지)
- layout/layout.html(각 영역들을 조합한 페이지)
- main/content.html(각 영역을 유지하고 동적으로 변환할 페이지)
- member/saveForm.html(각 영역을 유지하고 동적으로 변환할 페이지)
- layout/layout.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head th:replace="layout/head :: layout_head(~{::meta}, ~{::title}, ~{::link})">
</head>
<body class="nav-md">
<div class="container body">
<div class="main_container">
<div th:replace="~{layout/navBar :: layout_navBar}"></div>
<div th:replace="~{layout/header :: layout_header}"></div>
<div layout:fragment="layout_content"></div>
<!-- <div th:replace="~{layout/content :: layout_content}"></div>-->
<div th:replace="~{layout/footer :: layout_footer}"></div>
</div>
</div>
</body>
</html>
기본적으로 타임리프를 쓰기위해선 xmlns:th="http://www.thymeleaf.org" 설정을 해야하며 layout-dialect를 사용하는 페이지에선 xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"를 설정한다.
각 영역들을 지정할 땐 th:replace로 경로를 지정하며, 주된 content부분의 내용은 페이지마다 동적으로 변환할 것이기 때문에 layout:fragment를 지정한다. 또한 <head> 부분은 head.html 페이지에서 설정한 정보를 받기위하여 meta, title, link 요소를 파라미터로 받아오게 설정했다.
- layout/head.html
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="layout_head(meta, title, link)">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- Meta, title, CSS, favicons, etc. -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" th:href="@{/images/favicon.ico}" type="image/ico" />
<title>Gentelella Alela! | </title>
<!-- Bootstrap -->
<link th:href="@{/vendors/bootstrap/dist/css/bootstrap.min.css}" rel="stylesheet">
<!-- Font Awesome -->
<link th:href="@{/vendors/font-awesome/css/font-awesome.min.css}" rel="stylesheet">
<!-- NProgress -->
<link th:href="@{/vendors/nprogress/nprogress.css}" rel="stylesheet">
<!-- iCheck -->
<link th:href="@{/vendors/iCheck/skins/flat/green.css}" rel="stylesheet">
.
.
.
.
head부분은 <head>태그의 모든 설정부분을 그대로 넘기기 위해서 meta, title, link등 의 요소를 파라미터로 넘겼다. 현재 설정한 페이지의 요소들이 layout.html 파일의 내용으로 변경된다.
- layout/header.html
<html xmlns:th="http://www.thymeleaf.org">
<th:block th:fragment="layout_header">
<!-- top navigation -->
<div class="top_nav">
<div class="nav_menu">
<div class="nav toggle">
<a id="menu_toggle"><i class="fa fa-bars"></i></a>
</div>
.
.
.
.
- layout/navBar.html
<html xmlns:th="http://www.thymeleaf.org">
<th:block th:fragment="layout_navBar">
<div class="col-md-3 left_col">
<div class="left_col scroll-view">
<div class="navbar nav_title" style="border: 0;">
<a href="index.html" class="site_title"><i class="fa fa-paw"></i> <span>Gentelella Alela!</span></a>
</div>
<div class="clearfix"></div>
.
.
.
.
- layout/footer.html
<html xmlns:th="http://www.thymeleaf.org">
<th:block th:fragment="layout_footer">
<!-- footer content -->
<footer>
<div class="pull-right">
Gentelella - Bootstrap Admin Template by <a href="https://colorlib.com">Colorlib</a>
</div>
<div class="clearfix"></div>
</footer>
<!-- /footer content -->
</th:block>
</html>
layout.html 페이지에서 영역으로 쓰일 부분은 th:replace, 각 영역에 해당하는 페이지는 th:fragment로 지정하며 두 부분의 이름은 같아야 한다.
- main/content.html
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="layout/layout">
<th:block layout:fragment="layout_content">
<!-- page content -->
<div class="right_col" role="main">
<!-- top tiles -->
<div class="row" style="display: inline-block;" >
<div class="tile_count">
<div class="col-md-2 col-sm-4 tile_stats_count">
<span class="count_top"><i class="fa fa-user"></i> Total Users</span>
<div class="count">2500</div>
<span class="count_bottom"><i class="green">4% </i> From last Week</span>
</div>
.
.
.
.
.
layout.html 에서 동적으로 변경시킬 content가 들어갈 페이지 이기때문에 html 부분에 xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" 설정을 한다. 추가적으로 해당 페이지에서는 어떤 페이지의 fragment로 쓸지 알아야하기 때문에 layout:decorator 설정을하고 layout으로 쓸 페이지의 경로를 지정해준다.
해당 페이지는 페이지 레이아웃은 유지하면서 상황에따라 content 부분만 바꿀 것이기 때문에 위에서 지정했던 영역들과는 다르게 th:fragment가 아닌 layout:fragment로 설정한다. 마찬가지로 layout.html에서 지정했던 name과 동일하게 지정한다.
- member/saveForm.html
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="layout/layout">
<th:block layout:fragment="layout_content">
</th:block>
</html>
해당 페이지에도 content.html과 같은 설정을 했다. layout.html 페이지를 레이아웃으로 유지하면서 content 부분을 content.html과 saveForm.html 부분을 동적으로 변환하며 사용할 수 있다. 이러한 설정을 통해 다른 페이지를 추가했을 때도 같은 레이아웃을 적용할 수 있다.
'Spring' 카테고리의 다른 글
[Spring Boot] IoC(제어의 역전)와 DI(의존주입) 스프링 컨테이너 (1) | 2021.08.26 |
---|---|
[Spring Boot] 프로젝트 빌드하고 실행하기(.jar) (0) | 2021.08.17 |
[Spring Boot] 프로젝트 생성하기(Intellij) (3) | 2021.08.13 |