#타임리프 레이아웃
코드의 재사용이 가능한 부분을 템플릿화할 수 있게 도와주는 타임리프 라이브러리
#레이아웃을 사용하는 이유
타임리프의 insert나 replace 기능은 많이 사용하지만 이 기능에는 한가지 문제점이 있다.
대부분의 사이트는 탑, 바텀, 네이게이션바 등을 고정적으로 사용한다.
그래서 매 페이지마다 top(header), bottom, navigationBar를 insert 해주게된다.
insert를 사용하면 탑에 내용이 바뀐다면 탑만 수정해주면 모든 페이지의 탑이 바뀌게 된다.
그런데 만약 insert된 코드의 내용이 아니라 insert된 코드, 다른 코드들 간의 구조에 변화가 생긴다면
모든 페이지의 fragment들의 구조를 바꿔줘야 한다.
이런 한계를 커버해 줄 수 있는 기능이 layout이다.
기본적인 레이아웃의 사용법을 이미지화한 모습이다.
공통요소는 레이아웃에 담아두고 바뀌는 부분만 각각의 페이지에 작성하면 된다.
product.html 페이지로 forwarding, redirect되면 product.html 페이지의 코드들이 레이아웃에 merge되어 렌더링된다.
#Thymeleaf layout을 사용하기 위한 setting
gradle 추가
implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect', version: '3.1.0'
layout.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
layout을 사용할 파일
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="layout/layout(title='Recently Viewed')">
<head>
여기서 layout/layout은 사용할 layout의 root이다.
즉, resources패키지의 layout 패키지 안의 layout.html 파일이라는 뜻이다.
(title='Recently Viewed')는 부가적인 기능으로 필요하지 않으면 작성하지 않아도 되고 layout의 root만 작성해줘도 된다.
#layout의 기본적인 사용
layout.html
<th:block layout:fragment="content" />
layout을 사용할 파일
<th:block layout:fragment="content">
<!-- Page Content-->
<div class="container padding-bottom-3x mb-2">
<div class="row">
<!--profile component-->
<div class="col-lg-4" th:insert="~{mypage_component :: mypage(accountPage='recentview')}"></div>
<!--profile component 끝-->
<div class="col-lg-8">
<div class="padding-top-2x mt-2 hidden-lg-up"></div>
<div class="table-responsive wishlist-table margin-bottom-none">
<!-- recentView Table-->
<!-- 하위 태그들은 size==1이면 빈상자 이미지로 대체-->
<table class="table"
th:insert="~{myProduct-component :: product-table(from='recentview')}"></table>
<!-- recentView Table-->
</div>
<hr class="mb-4">
</div>
</div>
</div>
</th:block>
layout.html에 원하는 위치에 layout:fragment="이름" 속성을 지정해주고
그 위치에 들어갈 코드를 다른 파일에서
layout:fragment="이름" 속성을 가진 태그의 안에 작성해주면 된다.
*layout은 head body 모두 작성할것이기 때문에 당연히 html 파일의 구조를 제대로 작성할텐데
layout을 사용할 파일은 head가 필요하지 않을 수도 있다.
하지만 모든 구조를 갖춰서 작성해주는 것이 좋고, 사용하지 않는 fragment들이라도 작성해주는 것이 좋다.
예를들어 layout에 fragment로 navigation, contents, recommendation이 있다면
layout을 사용하는 product.html에 recommendation fragment를 사용하지 않아도 빈 fragment를 작성해준다면 fragment가 아닌 부분의 코드 위치를 잡는데도 도움이 될 것이다.
#layout head merge
레이아웃의 <head> 는 모든 페이지에서 공통으로 사용할 코드를 작성하면 된다.
다른 페이지에서 그 페이지에서만 사용할 css나 js가 있다면 그 페이지의 head에 작성하면
그 페이지에 작성된 head만 적용되는 것이 아니라 layout의 head와 merge되어 같이 적용된다.
#layout 변수 초기화 및 사용
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head></head>
<body>
<!-- content start -->
<div class="page-title" th:fragment="page-title(page_title)">
<div class="container">
<div class="column">
<h1 th:text="${page_title}">title</h1>
</div>
<div class="column">
<ul class="breadcrumbs">
<li><a href="index">Home</a></li>
<li class="separator"> </li>
<li th:text="${page_title}">title</li>
</ul>
</div>
</div>
</div>
<!-- content end -->
</body>
</html>
레이아웃에 변수를 선언하고 레이아웃을 사용하는 각 페이지마다 그 변수를 초기화하여 사용할 수 있다.
기존 타임리프에는 fragment명에 (변수 선언)하면 이후에 ${변수명}으로 사용할 수 있다.
레이아웃에서는
<th:block th:if="${title!=''}">
<div class="page-title"
th:insert="~{fragment/page-title::page-title(${title})}"
th:remove="tag"></div>
</th:block>
layout.html
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="layout/layout(title='Recently Viewed')">
recentview.html
레이아웃을 사용하는 파일에서 (변수명='value')라고 하면
layout.html의 ${title}에 value값이 대입된다.
'Java > Spring Boot' 카테고리의 다른 글
JPA Object Relation Mapping (0) | 2023.10.11 |
---|---|
JPA 계층형 게시판 (0) | 2023.10.10 |
Spring Data JPA begins (0) | 2023.10.06 |
Spring CRUD with RestAPI (0) | 2023.09.20 |
Spring addViewControllers (0) | 2023.09.14 |