Search
Duplicate

ํƒ€์ž„๋ฆฌํ”„ ๋ ˆ์ด์•„์›ƒ ๋‹ค์ด์–ผ๋ ‰ํŠธ

ํƒ€์ž„๋ฆฌํ”„ ๋ ˆ์ด์•„์›ƒ ๋‹ค์ด์–ผ๋ ‰ํŠธ

โ€ข
ํƒ€์ž„๋ฆฌํ”„ ๋ ˆ์ด์•„์›ƒ ๋‹ค์ด์–ผ๋ ‰ํŠธ ์˜์กด์„ฑ
โ—ฆ
build.gradle
โ€ข
ํ”„๋ž˜๊ทธ๋จผํŠธ
โ€ข
๋ ˆ์ด์•„์›ƒ

ํƒ€์ž„๋ฆฌํ”„ ๋ ˆ์ด์•„์›ƒ ๋‹ค์ด์–ผ๋ ‰ํŠธ ์˜์กด์„ฑ

// ํƒ€์ž„๋ฆฌํ”„ ๋‹ค์ด์–ผ๋ ‰ํŠธ ๋ ˆ์ด์•„์›ƒ implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
Java
๋ณต์‚ฌ

build.gradle

plugins { id 'java' id 'war' id 'org.springframework.boot' version '3.2.5' id 'io.spring.dependency-management' version '1.1.4' } group = 'com.aloha' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' annotationProcessor 'org.projectlombok:lombok' providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' testImplementation 'org.springframework.boot:spring-boot-starter-test' // ํƒ€์ž„๋ฆฌํ”„ ๋‹ค์ด์–ผ๋ ‰ํŠธ ๋ ˆ์ด์•„์›ƒ implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect' } tasks.named('test') { useJUnitPlatform() }
Java
๋ณต์‚ฌ

ํ”„๋ž˜๊ทธ๋จผํŠธ (Fragment)

ํƒ€์ž„๋ฆฌํ”„ ๋ ˆ์ด์•„์›ƒ์˜ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉํ•  ๋ถ€๋ถ„
UI ์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๊ตฌ์„ฑ ์š”์†Œ๋“ค์„ ๋ณ„๋„์˜ HTML ํŒŒ์ผ๋กœ ๋งŒ๋“ ๋‹ค. ์ฃผ๋กœ ํ—ค๋”, ํ‘ธํ„ฐ, ์‚ฌ์ด๋“œ๋ฐ” ๋“ฑ์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ”„๋ž˜๊ทธ๋จผํŠธ ์‹ค์ŠตํŒŒ์ผ

โ€ข
~/fragment/header.html
โ€ข
~/fragment/footer.html
โ€ข
~/fragment/link.html
โ€ข
~/fragment/script.html

~/fragment/header.html

<!-- ํ”„๋ž˜๊ทธ๋จผํŠธ : ๋ ˆ์ด์•„์›ƒ์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉํ•  UI --> <!-- th:fragment="ํ”„๋ž˜๊ทธ๋จผํŠธ ๋ช…" --> <th:block th:fragment="header"> <header> <ul> <li><a href="/user">์‚ฌ์šฉ์ž</a></li> <li><a href="/admin">๊ด€๋ฆฌ์ž</a></li> </ul> <ul> <li><a href="/login">๋กœ๊ทธ์ธ</a></li> <li><a href="/join">ํšŒ์›๊ฐ€์ž…</a></li> </ul> </header> </th:block>
HTML
๋ณต์‚ฌ

~/fragment/footer.html

<th:block th:fragment="footer"> <footer> <p>copyright ALL RIGHT RESERVED</p> </footer> </th:block>
HTML
๋ณต์‚ฌ

~/fragment/link.html

<th:block th:fragment="link"> <link rel="stylesheet" href="/css/style.css"> </th:block>
HTML
๋ณต์‚ฌ

~/fragment/script.html

<th:block th:fragment="script"> <!-- js ๊ฐ€์ ธ์˜ค๋Š” ์ˆœ์„œ--> <!-- jQuery --> <!-- jQuery ๊ธฐ๋ฐ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ --> <!-- ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ --> <!-- ์‚ฌ์šฉ์ž ์ •์˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ --> <script src="/js/script.js" ></script> </th:block>
HTML
๋ณต์‚ฌ

๋ ˆ์ด์•„์›ƒ (Layout)

ํŠน์ • ํŽ˜์ด์ง€์— UI๋ฅผ ํ•˜๋‚˜์˜ ํ…œํ”Œ๋ฆฟ์œผ๋กœ ๋ฏธ๋ฆฌ ๊ตฌ์„ฑ ํ•ด๋†“์€ ์˜์—ญ
๋ ˆ์ด์•„์›ƒ ํ…œํ”Œ๋ฆฟ์„ ํ”„๋ž˜๊ทธ๋จผํŠธ๋กœ ๊ตฌ์„ฑํ•˜๊ณ , ๊ฐ ํŽ˜์ด์ง€๋งˆ๋‹ค ๋‹ค๋ฅด๊ฒŒ ๋ณด์—ฌ์ค„ ์ปจํ…์ธ  ์˜์—ญ์„ ์ง€์ •ํ•ด์„œ ๋ฏธ๋ฆฌ ์งœ์—ฌ์ง„ ๋ ˆ์ด์•„์›ƒ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ์š”์†Œ

~/layout/main_layout.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- link --> <th:block th:replace="~{fragment/link::link}"></th:block> </head> <body> <!-- header --> <th:block th:replace="~{fragment/header::header}"></th:block> <!-- โญ content --> <!-- layout:fragment="๋ ˆ์ด์•„์›ƒ์˜ ํ”„๋ ˆ๊ทธ๋จผํŠธ ์˜์—ญ ์ด๋ฆ„" --> <th:block layout:fragment="content"></th:block> <!-- footer --> <th:block th:replace="~{fragment/footer::footer}"></th:block> <!-- script --> <th:block th:replace="~{fragment/script::script}"></th:block> </body> </html>
HTML
๋ณต์‚ฌ

index.html

์—ฌ๊ธฐ์„œ๋Š” ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ๊ฐ€์ ธ์™€์„œ ๊ณตํ†ต ๋ ˆ์ด์•„์›ƒ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <th:block th:replace="~{fragment/link::link}"></th:block> </head> <body> <!-- th:replace : ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์†์„ฑ --> <!-- th:replace="~{ํด๋”๋ช…/ํŒŒ์ผ๋ช…::ํ”„๋ž˜๊ทธ๋จผํŠธ๋ช…}" --> <th:block th:replace="~{fragment/header::header}"></th:block> <div class="container"> <h3>CONTENT</h3> </div> <th:block th:replace="~{fragment/footer::footer}"></th:block> <th:block th:replace="~{fragment/script::script}"></th:block> </body> </html>
HTML
๋ณต์‚ฌ

main.html

<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{/layout/main_layout}" > <!-- โญ layout:decorate="~{/๋ ˆ์ด์•„์›ƒ ๊ฒฝ๋กœ/๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ๋ช…}" --> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>๋ฉ”์ธ ํ™”๋ฉด</title> </head> <!-- โญ layout:fragment="๋ ˆ์ด์•„์›ƒ ํ”„๋ ˆ๊ทธ๋จผํŠธ ์ด๋ฆ„" --> <body layout:fragment="content"> <div class="container"> <h3>CONTENT</h3> </div> </body> </html>
HTML
๋ณต์‚ฌ

style.css

* { margin: 0; padding: 0; box-sizing: border-box; } a { color: black; text-decoration: none; } ul { list-style-type: none; } header { height: 80px; background-color: lightslategray; display: flex; justify-content: space-between; align-items: center; } header ul { display: flex; height: 100%; padding: 0 20px; } header ul li { min-width: 100px; } header ul li a { display: inline-block; min-width: 120px; line-height: 80px; text-align: center; color: white; } header ul li a:hover { font-weight: bold; } .container { border: 1px solid black; max-width: 1024px; min-height: 300px; margin: 0 auto; padding: 12px; } footer { background-color: black; color: white; min-height: 100px; text-align: center; } footer p { line-height: 100px; }
CSS
๋ณต์‚ฌ