반응형
해당 글에서는 Spring Boot에서 Thymeleaf에 대한 환경 구성을 하고 Thymeleaf Layout을 적용하기 위한 방법에 대해서 공유합니다.
1) 개발환경
💡 Thymeleaf Template / Thymeleaf Template Layout을 구성을 위한 개발환경입니다.
개발환경 | 버전 |
java | 1.8 |
Spring Boot | 2.7.4 |
빌드관리도구 | Gradle 7.5 |
개발 툴 | IntelliJ IDEA 2022.3 |
spring-boot-starter-thymeleaf | 2.7.4 |
thymeleaf-layout-dialect | 3.1.0 |
2) 적용 계기
💡 Thymeleaf Template을 사용하면서 Header / Footer / SideBar / Body에 대한 각각의 구성하는 영역이 필요했고 공통으로 사용하는 라이브러리, JS, CSS에 대한 관리가 필요하였습니다.
💡모든 페이지마다 이 설정들을 가지고 다니기에는 관리가 어렵기 때문에 기초 구성을 위한 Layout을 적용하기로 결정하였습니다.
3) Thymeleaf-layout-dialect
💡Thymeleaf-layout-dialect 란?
- Thymeleaf 내에 코드의 재사용성을 위해서 레이아웃과 재 사용이 가능한 템플릿을 구축할 수 있는 오픈소스 라이브러리를 의미합니다.
💡 [참고] Thymeleaf-layout 구조
- Header 영역, Navigation 영역, Sidebar 영역, Content 영역, Footer 영역으로 구분이 됩니다.
[참고] Maven Resitory - 오픈소스 라이브러리 버전
https://mvnrepository.com/artifact/nz.net.ultraq.thymeleaf/thymeleaf-layout-dialect
[참고] 공식 사이트 - Thymeleaf-layout 영역
4) Thymeleaf / Thymeleaf Layout 환경 설정
1. build.gradle 의존성을 추가합니다.
💡 Thymeleaf와 Thymeleaf Layout에 대한 의존성을 추가합니다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' // Thymeleaf Template
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect' // Thymeleaf Layout
}
2. application.properties / yml 파일 내에 설정을 합니다.
💡 Thymeleaf 관련한 환경설정을 합니다.
# Properties 파일 - Thymeleaf 설정
spring.thymeleaf.enabled=true
spring.thymeleaf.cache=false
spring.thymeleaf.check-template-location=true
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
# yaml/yml 파일 - Thymeleaf 설정
thymeleaf:
cache: false
check-template-location: true
prefix: classpath:/templates/
suffix: .html
enabled: true
5) 구성하기
1. 폴더 구조 구성
💡 폴더 구조에 대한 설명
폴더 구조 | 설명 |
templates | 환경 설정에서 Thymeleaf가 시작되는 페이지로 지정한 최상위 디렉터리입니다. |
templates/common | 공통으로 사용되는 페이지에 대한 상위 디렉터리로 구성하였습니다. |
templates/common/fragment | 모든 페이지에서 출력이 되는 header, footer, config에 대한 디렉터리로 구성하였습니다. |
templates/common/layout | Fragments에 구성한 파일들을 해당 페이지에서 엮어주는 용도로 디렉터리를 구성하였습니다. |
templates/pages | 업무 페이지를 관리하는 상위 디렉터리로 구성하였습니다. |
templates/pages/test | 업무 페이지별 디렉터리로 구성하였습니다. |
💡 파일에 대한 설명
파일 명 | 설명 |
config.html | - 공통 JS, CSS를 초기 파일에 불러올 수 있도록 구성하였습니다. |
header.html | - Header 영역의 화면에 대한 목적으로 구성하였습니다. |
footer.html | - Footer 영역의 화면에 대한 목적으로 구성하였습니다. |
defaultLayout.html | - 구성한 파일들(config, header, footer, content)을 엮어주기 위한 목적으로 구성하였습니다. |
test.html | - defaultLayout을 불러오며 Content 영역에 해당하고 화면 별 내용이 들어가는 목적으로 구성하였습니다 |
2. 화면 구성
💡 실제 파일을 구성하는 데 사용하는 Thymleaf 및 Thymeleaf-layout의 ‘속성들’에 대한 설명들입니다.
Thymeleaf-Layout 속성 | 설명 |
xmlns:th="http://www.thymeleaf.org" | - Thymeleaf Template이라고 선언합니다 |
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" | - Thymeleaf-layout을 사용함을 선언합니다. |
layout:fragment | - 해당 속성은 지정한 영역(태그 범위)을 기준으로 Fragment임을 선언합니다. |
th:replace | - 해당 속성은 fragment에서 지정된 태그 영역을 불러오는데 사용합니다. - 경로로 해당 파일을 찾아서 :: 을 이용하여 Alias를 지정합니다. |
layout:decorate | - 해당 속성은 구성한 레이아웃을 경로로 불러올때 사용합니다. - 업무 페이지에서 레이아웃 경로를 불러와야 Fragment를 사용할 수 있습니다. |
3. 파일 구성 1 - Header Layout
💡 해당 페이지에서는 th:fragment="HeaderFragment"를 통해서 fragment이고 이름은 HeaderFragment임을 선언합니다.
💡 해당 영역에서는 Header를 구성하는 공간입니다.
<!DOCTYPE html>
<!-- Thymeleaf 선언 / headerFragment 임을 선언-->
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
th:fragment="HeaderFragment">
<div style="border: solid 1px yellow">
<h1>Header 영역입니다.</h1>
</div>
</html>
4. 파일 구성 2 - Footer Layout
💡 해당 페이지에서는 th:fragment="FooterFragment"를 통해서 fragment이고 이름은 FooterFragment임을 선언합니다.
💡 해당 영역에서는 Footer를 구성하는 공간입니다.
<!DOCTYPE html>
<!-- Thymeleaf 선언 / FooterFragment 임을 선언-->
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
th:fragment="FooterFragment">
<div style="border: solid 1px blue">
<h1>Footer 영역입니다.</h1>
</div>
</html>
5. 파일 구성 3 - Config Layout
💡 해당 페이지에서는 th:fragment="ConfigFragment"를 통해서 fragment이고 이름은 ConfigFragment임을 선언합니다. 💡 해당 영역에서는 Config를 구성하는 공간이며 프로젝트 내부에 다운로드한 jquery, jquery-ui의 js 파일을 불러오고 있고 jquery-ui.min.css 파일을 불러오고 있습니다.
<!DOCTYPE html>
<!--Thymeleaf, ConfigFragment 선언-->
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
th:fragment="ConfigFragment">
<head>
<!--Common Head-->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="viewport"
content="width=device-width, maximum-scale=1.0, minimum-scale=1, user-scalable=yes,initial-scale=1.0"/>
<title></title>
<!--Common JS-->
<script th:inline="javascript" type="text/javascript" th:src="@{/lib/jquery-3.6.1.min.js}"></script>
<script th:inline="javascript" type="text/javascript" th:src="@{/lib/jquery-ui.min.js}"></script>
<!--Common CSS -->
<link th:inline="css" th:href="@{/lib/jquery-ui.min.css}" rel="stylesheet"/>
</head>
</html>
6. 파일 구성 4 - Default Layout
💡 해당 영역에서는 위에서 구성한 Config, header, footer를 Alias를 주고 *Fragment 형태로 이름을 줘서 구성을 하였습니다. 그리고 Content 영역을 참조하였습니다.
<!DOCTYPE html>
<!--라이브러리 참조 : Thymeleaf & Thymeleaf Layout -->
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<!--공통 JS / CSS 영역을 관리하는 환경 영역-->
<head th:replace="common/fragments/config :: ConfigFragment">
<title layout:title-pattern="$LAYOUT_TITLE : $CONTENT_TITLE">공통 타이틀</title>
</head>
<body>
<!--Header 영역을 참조합니다.-->
<header th:replace="common/fragments/header :: HeaderFragment"></header>
<!--Content 내용 영역을 참조합니다-->
<th:block layout:fragment="Content"></th:block>
<!--Footer 영역을 참조합니다.-->
<footer th:replace="common/fragments/footer :: FooterFragment"></footer>
</body>
</html>
7. 파일 구성 5 - 업무 페이지(test.html)
💡해당 영역에서는 모두 구성된 ‘defaultLayout’을 참조합니다.
💡 layout:fragment="Content" 속성을 통하여 본인이 Cotent 영역임을 지정합니다. 또한 업무 페이지에서는 style th:inline="css" type="text/css"와 script th:inline="javascript" type="text/javascript"를 통해서 인라인으로 사용이 가능합니다.
<!DOCTYPE html>
<!-- Default Layout Import-->
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{common/layouts/defaultLayout}"
layout:fragment="Content"
>
<head>
<title>테스트 페이지 </title>
<!-- inline CSS 영역-->
<style th:inline="css" type="text/css">
body {
margin: 30px;
border: 1px solid red;
}
</style>
<!-- inline JS 영역-->
<script th:inline="javascript" type="text/javascript">
$(document).ready(() => {
alert("페이지가 시작됩니다.")
});
</script>
</head>
<body>
<div>
<h1>Content 영역입니다.</h1>
</div>
</body>
</html>
8. 파일 구성 6 - API 호출 영역
💡 resource 디렉터리의 templates 영역까지 참조를 해둔 상태여서 그 하위 "pages/test/testPage"를 불러오도록 리턴하였습니다.
package com.adjh.multiflexapi.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Slf4j
@Controller
public class MainController {
@GetMapping("/")
public String selectImageList(Model model) {
model.addAttribute("title", "");
return "pages/test/testPage";
}
}
6) 실행화면
1. 내부 JS/CSS 파일들을 로드 확인 완료
2. 레이아웃 구성 확인 완료
오늘도 감사합니다😀
반응형
'Java > Spring Boot' 카테고리의 다른 글
[Java] Global Exception 이해하고 구성하기 : Controller Exception (5) | 2022.11.13 |
---|---|
[Java/Library] Spring Boot Validation 이해하기 : 데이터 유효성 검증 (4) | 2022.11.08 |
[Java/Library] Slf4j - Log4j2 이해하고 설정하기 (2) | 2022.10.21 |
[Java/Library] HikariCP 이해하고 적용하기 (with. MyBatis) (0) | 2022.10.20 |
[Java/Library] Spring Boot 2.x 환경에서 Swagger 이해하고 적용하기 : SpringDoc openAPI UI (2) | 2022.10.18 |