start.spring.io에서 프로젝트 설정을 해줍니다.
git을 설치한 후에
IntelliJ VCS 메뉴에서 git을 연동하고 github에 repository를 만들어줍니다.
버전 관리가 되지 않은 파일들을 선택한 후에 커밋해줍니다.
templates 폴더 밑에 index.html 파일을 생성한 후 BootStrap에서 가져온 코드를 붙여 넣어줍니다.
<!doctype html>
<html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<h1>Hello, world!</h1>
<!-- Optional JavaScript; choose one of the two! -->
<!-- Option 1: jQuery and Bootstrap Bundle (includes Popper) -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
<!-- Option 2: Separate Popper and Bootstrap JS -->
<!--
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.min.js" integrity="sha384-+sLIOodYLS7CIrQpBjl+C7nPvqq+FbNUBDunl/OZv93DB7Ln/533i8e/mZXLi/P+" crossorigin="anonymous"></script>
-->
</body>
</html>
아래 템플릿 사용
https://getbootstrap.com/docs/4.6/examples/starter-template/
소스코드 보기를 한 후 아래 코드를 복사하여 indexl.html body 부분에 붙여 넣어줍니다.
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item">
<a class="nav-link disabled">Disabled</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-expanded="false">Dropdown</a>
<div class="dropdown-menu">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</li>
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
<button class="btn btn-secondary my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
<main role="main" class="container">
<div class="starter-template">
<h1>Bootstrap starter template</h1>
<p class="lead">Use this document as a way to quickly start any new project.<br> All you get is this text and a mostly barebones HTML document.</p>
</div>
</main>
java -> com.project.myhome 폴더 밑에 controller 패키지를 생성한 후 HomeController Class를 생성합니다.
첫 페이지는 index.html로 경로 지정없이 작성해줍니다.
package com.project.myhome.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping
public String index(){
return "index";
}
}
Application 실행 후 localhost:8080를 검색창에 입력 후 들어가면 화면이 스타일이 적용 되지 않은 것을 확인할 수 있습니다.
index.html 파일에
<link href="starter-template.css" rel="stylesheet">
위의 코드를 추가한 후에 static 폴더 밑에 starter-template.css을 생성한 후 아래 코드를 넣어줍니다.
body {
padding-top: 5rem;
}
.starter-template {
padding: 3rem 1.5rem;
text-align: center;
}
서식을 적용하니 제대로 나오는 것을 알 수 있습니다.
현재 static 폴더에는 css파일을, templates 폴더에는 thymeleaf파일을 넣었습니다.
index.html 상단 메뉴의 이름과 내용을 바꾸고 사용하지 않을 기능은 주석처리를 해줍니다.
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<link href="starter-template.css" rel="stylesheet">
<title>Hello, world!</title>
</head>
<body>
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="#">Spring Boot Tutorial</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault"
aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">게시판</a>
</li>
<!-- <li class="nav-item">-->
<!-- <a class="nav-link disabled">Disabled</a>-->
<!-- </li>-->
<!-- <li class="nav-item dropdown">-->
<!-- <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-expanded="false">Dropdown</a>-->
<!-- <div class="dropdown-menu">-->
<!-- <a class="dropdown-item" href="#">Action</a>-->
<!-- <a class="dropdown-item" href="#">Another action</a>-->
<!-- <a class="dropdown-item" href="#">Something else here</a>-->
<!-- </div>-->
<!-- </li>-->
</ul>
<!-- <form class="form-inline my-2 my-lg-0">-->
<!-- <input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">-->
<!-- <button class="btn btn-secondary my-2 my-sm-0" type="submit">Search</button>-->
<!-- </form>-->
</div>
</nav>
<main role="main" class="container">
<div class="starter-template">
<h1>Spring Boot Tutorial</h1>
<p class="lead">Spring Boot를 이용해 웹 페이지 제작<br>
Spring Security, JPA를 이용해 보안 설정과 데이터 다루기.</p>
</div>
</main>
<!-- Optional JavaScript; choose one of the two! -->
<!-- Option 1: jQuery and Bootstrap Bundle (includes Popper) -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct"
crossorigin="anonymous"></script>
<!-- Option 2: Separate Popper and Bootstrap JS -->
<!--
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.min.js" integrity="sha384-+sLIOodYLS7CIrQpBjl+C7nPvqq+FbNUBDunl/OZv93DB7Ln/533i8e/mZXLi/P+" crossorigin="anonymous"></script>
-->
</body>
</html>
th:fragment -> Header, Footer, Navigation bar 같이 모든 페이지에 보여져야하는 항목인 경우 따로 분리해서 관리해줍니다.
<footer th:fragment="copy">
© 2011 The Good Thymes Virtual Grocery
</footer>
<div th:replace="footer :: copy"></div>
-> copy라는 fragment를 만든 후 footer라는 파일에 사용
templates 폴더 밑에 fragments 폴더 생성 후 common.html 파일을 생성해줍니다.
common.html 파일 밑에 thymeleaf docs에서 가져온 코드를 넣고 index.html에 있는 내부 코드를 가져와 붙여넣어줍니다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top" th:fragment="menu">
<a class="navbar-brand" href="#">Spring Boot Tutorial</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault"
aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">게시판</a>
</li>
<!-- <li class="nav-item">-->
<!-- <a class="nav-link disabled">Disabled</a>-->
<!-- </li>-->
<!-- <li class="nav-item dropdown">-->
<!-- <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-expanded="false">Dropdown</a>-->
<!-- <div class="dropdown-menu">-->
<!-- <a class="dropdown-item" href="#">Action</a>-->
<!-- <a class="dropdown-item" href="#">Another action</a>-->
<!-- <a class="dropdown-item" href="#">Something else here</a>-->
<!-- </div>-->
<!-- </li>-->
</ul>
<!-- <form class="form-inline my-2 my-lg-0">-->
<!-- <input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">-->
<!-- <button class="btn btn-secondary my-2 my-sm-0" type="submit">Search</button>-->
<!-- </form>-->
</div>
</nav>
</body>
</html>
index.html nav에 아래 코드를 추가해줍니다.
th:replace="fragments/common :: menu"
controller 폴더 밑에 BoardController 클래스를 생성합니다.
package com.project.myhome.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/board")
public class BoardController {
@GetMapping("/list")
public String list(){
return "board/list";
}
}
controller를 이용하여 경로를 지정해줍니다.
templates 폴더 밑에 board 폴더를 만든 후 list.html 파일을 생성 후 title, h1 태그 수정 후 context root를 변경해줍니다.
-> context root를 변경하지 않으면 starter-template.css의 위치를 찾지 못한다.
글자 표시될 div의 class를 변경해줍니다.
<div class="container">
<h2>게시판</h2>
</div>
localhost:8080/board/list에 들어가면 화면이 잘 나오는 것을 볼 수 있습니다.
index.html과 list.html의 head부분이 겹치기 때문에 common.html에 넣어줍니다.
title은 겹치면 안 되기 때문에 thymeleaf에 있는 매개 변수로 가져오는 코드를 작성해줍니다.
common.html
<head th:fragment="head(title)">
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<link href="starter-template.css" rel="stylesheet">
<title th:text="${title}">Hello, world!</title>
</head>
<link href="starter-template.css" th:href="@{/starter-template.css}" rel="stylesheet">
index.html
<head th:replace="fragments/common :: head('Hello, Spring Boot!')">
list.html
<head th:replace="fragments/common :: head('게시판')">
common.html 수정
메뉴바에서 홈이나 게시판을 클릭할 시 그 부분만 active상태로 변경되게 합니다.
thymeleaf 문법에 있는 classappend 속성을 이용해줍니다.
<tr th:each="prod : ${prods}" class="row" th:classappend="${prodStat.odd}? 'odd'">
조건문이 true인 경우에만 적용됩니다.
index.html과 list.html에서 fragments를 호출하는 menu에 parameter를 사용합니다.
list.html
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top" th:replace="fragments/common :: menu('board')">
index.html
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top" th:replace="fragments/common :: menu('home')">
common.html
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top" th:fragment="menu(menu)">
<li class="nav-item" th:classappend="${menu} == 'home' ? 'active'">
<a class="nav-link" href="#" th:href="@{/}">Home <span class="sr-only" th:if="${menu} == 'home'">(current)</span></a>
</li>
<li class="nav-item" th:classappend="${menu} == 'board' ? 'active'">
<a class="nav-link" href="#" th:href="@{/board/list}">게시판 <span class="sr-only" th:if="${menu} == 'board'">(current)</span></a>
</li>
링크 연결과 메뉴바에 불이 잘 들어오는 것을 확인할 수 있습니다.