안녕하세요 코이킹입니다.
이번 포스트는 타임리프 템플릿 결합과 부트스트랩 적용에 대한 내용이 되겠습니다.
1. 목표
- 타임리프의 공통 템플릿과 각 기능별 템플릿을 결합하여 브라우저에 표시할 수 있다.
- 스프링부트+타임리프를 사용할 때 부트스트랩과 같은 정적 콘텐츠를 적용할 수 있다.
2. 템플릿의 레이아웃을 합치는 이유
대부분의 웹 사이트의 URL로 구분된 독립적인 페이지를 보면, 상단(검색창이나, 로그인 / 회원가입과 같은 기능)과 하단 (카피라이트의 문구나 사이트 맵)은 거의 변화가 없고, 중단의 콘텐츠만 변하는 경우가 많습니다.
지금까지 구현해온 게시판에 이제 부터 회원가입과 로그인 기능을 추가하려고 하는데, 이때 각각의 타임리프 템플릿에
반복되는 부분을 똑같이 복사붙여 넣기를 하는 것은 작업량도 늘 것이며, 유지보수와 관리에 드는 시간도 늘어날 것입니다.
따라서 이 포스트에서는 이 반복되는 부분을 각각의 기능별 템플릿과 결합하여 재활용하는 방법에 대해서 알아보려 합니다.
결론부터 적어보자면, thymeleaf-layout-dialect라는 라이브러리를 사용하여 반복되는 부분의 템플릿(헤더와 푸터)과 독립적인 템플릿을 결합하여 브라우저에 표시할 겁니다.
3. 소스코드와 해석
1) build.gradle
plugins {
id 'org.springframework.boot' version '2.6.8'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.sb.template'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
all*.exclude module : 'spring-boot-starter-logging'
}
repositories {
mavenCentral()
}
dependencies {
// For develop
developmentOnly 'org.springframework.boot:spring-boot-devtools'
// Web
implementation 'org.springframework.boot:spring-boot-starter-web'
// thymeleaf
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
// Test
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// DB
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'mysql:mysql-connector-java'
// lombok
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
// Log4j
implementation 'org.springframework.boot:spring-boot-starter-log4j2'
// Validation
implementation 'org.springframework.boot:spring-boot-starter-validation'
// thymeleaf-layout-dialect
implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect', version: '3.1.0'
// bootstrap
implementation group: 'org.webjars', name: 'bootstrap', version: '5.1.3'
// JQuery
implementation group: 'org.webjars', name: 'jquery', version: '3.6.0'
}
tasks.named('test') {
useJUnitPlatform()
}
- 51행 : 타임리프 템플릿 결합을 위한 라이브러리 의존성 추가
- 54행 : 디자인 적용을 위한 부트스트랩 라이브러리 의존성 추가
- 57행 : 제이쿼리 라이브러리 의존성 추가
※ 템플릿 결합 시 구조
템플릿이 결합 되는 것을 이미지화해보면 다음과 같습니다.
2) 전체 레이아웃 구조 템플릿 : /template-springboot/src/main/resources/templates/common/layout.html
- 웹 페이지의 전체적인 레이아웃의 형태를 정의하는 템플릿입니다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head th:replace="common/common_head :: commonHead">
</head>
<body>
<div class="container">
<div th:replace="common/common_header :: commonHeader"></div>
<div th:replace="common/common_body :: commonBody"></div>
</div>
</body>
</html>
- 5행 : <head> 태그를 부분을 템플릿화 하겠다는 코드로, common/common_head.html 파일에서 th:fragment속성의 값이 "commonHead"인 부분을 가져오겠다는 의미.
- 10행 : 웹 페이지 상단의 공통메뉴 부분을 템플릿화 하겠다는 코드로, common/common_header.html 파일에서 th:fragment속성의 값이 "commonHeader"인 부분을 가져오겠다는 의미.
- 11행 : 웹 페이지의 바디 부분을 템플릿화 하겠다는 코드로, common/common_body.html파일에서 th:fragment속성의 값이"commonBody"인 부분을 가져오겠다는 의미.
3) <head> 태그의 탬플릿 : /template-springboot/src/main/resources/templates/common/common_head.html
<!DOCTYPE html>
<html
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head th:fragment="commonHead">
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, inital-scale=1.0"/>
<title>Template-SpringBoot</title>
<link th:href="@{/webjars/bootstrap/5.1.3/css/bootstrap.min.css}" rel="stylesheet"></link>
<script th:src="@{/webjars/jquery/3.6.0/jquery.min.js}"></script>
<!-- CSS setting each page -->
<th:block layout:fragment="custom_css"></th:block>
</head>
</html>
- 5행 : layout.html의 템플릿으로 사용하기 위한 값 설정.
- 12~13행 : 부트스트랩 CSS와 제이쿼리를 적용하기 위한 코드.
※ 라이브러리 (. jar)로 추가한 정적 콘텐츠의 경로 확인 방법
-> webjars/이하의 경로를 써주면 된다.
4) 페이지의 상단의 고정된 메뉴 템플릿: /template-springboot/src/main/resources/templates/common/common_header.html
<!DOCTYPE html>
<html
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<body>
<div th:fragment="commonHeader">
<header class="bg-dark text-white d-flex flex-wrap align-items-center justify-content-center justify-content-md-between border-bottom">
<h3>
<a href="/" class="d-flex align-items-center col-md-3 text-white text-decoration-none px-1 py-1 mx-1 my-1">
Template-SpringBoot
</a>
</h3>
<div class="nav col-md-3 px-1">
<div class="nav-item px-1 py-1">
<button class="btn btn-primary" id="write-board" type="button" onclick="location.href='/auth/login'">Login Member</button>
</div>
<div class="nav-item px-1 py-1">
<button class="btn btn-success me-2" id="write-board" type="button" onclick="location.href='/auth/join'">Join Member</button>
</div>
</div>
</header>
</div>
</body>
</html>
- 7행 : layout.html의 템플릿으로 사용하기 위한 값 설정.
5) 페이지의 바디 템플릿 : /template-springboot/src/main/resources/templates/common/common_body.html
<!DOCTYPE html>
<html
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<body>
<div th:fragment="commonBody">
<th:block layout:fragment="contents"></th:block>
<br>
<div class="bg-dark text-white border-bottom" align="center">
Copyright 2022. koiking. All rights reserved.
</div>
</div>
</body>
</html>
- 8행 : layout.html의 템플릿으로 사용하기 위한 값설정.
- 9행 : 바디안에 들어갈 콘텐츠 부분을 템플릿화 하겠다는 코드로, layout:fragment속성의 값이 "contents"인 부분을 가져오겠다는 의미.
6) 컨텐츠 템플릿 : /template-springboot/src/main/resources/templates/board/list.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{common/layout}">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, inital-scale=1.0"/>
</head>
<body>
<div layout:fragment="contents">
<div class="nav justify-content-end px-5 pt-2">
<button class="btn btn-info text-white" id="write-board" type="button" onclick="location.href='/board/write'">
Contents Write
</button>
</div>
<hr/>
<div>
<table class="table" border="1">
<thead class="table-dark">
...
...
...
</div>
</body>
</html>
- 3행 : 템플릿 결합을 위한, 라이브러리를 사용하겠다는 선언.
- 4행 : 페이지의 전체 레이아웃 템플릿이 어디인지 정의. layout.html을 지정하고 있다.
- 11행 : 페이지의 바디(common_body.html)의 컨텐츠 부분의 템플릿으로서 사용하겠다는 선언.
4. 동작확인
5. 전체 소스코드
https://github.com/leeyoungseung/template-springboot/tree/feature/layout-dialect
이것으로 타임리프 템플릿 결합과 부트스트랩 적용에 대한 포스트는 마치겠습니다.
다음 포스트는 회원가입에 대한 내용이 되겠습니다.
'프로그래밍 > Springboot-토이프로젝트' 카테고리의 다른 글
【게시판-10】로그인 / 로그아웃 (1) | 2022.09.21 |
---|---|
【게시판-09】회원가입 (1) | 2022.09.20 |
【게시판-07】페이징 처리 (1) | 2022.09.16 |
【게시판-번외06】예외처리 (0) | 2022.09.16 |
【게시판-번외05】유효성 검사 (0) | 2022.09.14 |
댓글