레퍼런스 : https://velog.io/@max9106/Spring-Boot-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%83%9D%EC%84%B1
프로젝트 전체 소스코드 : https://github.com/rawfishthelgh/boardcrud.git
개발 환경
IDEA: IntelliJ
Java:11
Spring Boot 2.7.2
Db : mysql+jpa
프로젝트 생성
MySql 연결
- DBCP설정
*DBCP란? : database connection pool의 약자다. 커넥션 풀이란 웹 컨테이너(WAS)가 실행되면서 DB와 미리 connection(연결)을 해놓은 객체들을 pool에 저장해두었다가. 클라이언트 요청이 오면 connection을 빌려주고, 처리가 끝나면 다시 connection을 반납받아 pool에 저장하는 방식이다. 자바에서 db에 직접 접근하면 매번 사용자가 요청을 할 때마다 드라이버를 로드하고 커넥션 객체를 생성하여 연결하고 종료하기 때문에 매우 비효율적이므로 커넥션 풀을 사용한다.
자세한 내용 확인 : https://linked2ev.github.io/spring/2019/08/14/Spring-3-%EC%BB%A4%EB%84%A5%EC%85%98-%ED%92%80%EC%9D%B4%EB%9E%80/
#DBCP설정
spring.datasource.hikari.maximum-pool-size=4
- Mysql 의존성 추가
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'mysql:mysql-connector-java' // MySql의존성추가
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'mysql:mysql-connector-java'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
- 도커 활용 mysql 설치 및 연동
docker run -p 3306:3306 --name mysql_boot -e MYSQL_ROOT_PASSWORD=1 -e MYSQL_DATABASE=springboot -e MYSQL_USER=rg970604 -e MYSQL_PASSWORD=1234 -d mysql
MYSQL_USER=사용할 유저이름, MYSQL_PASSWORD=사용할 비밀번호를 설정해 터미널에서 실행시켜준다.
docker ps를 터미널에 입력해 해당 인스턴스가 생성되었는지 확인한다.
application.properties에 위 정보를 활용해 mysql 접속 정보를 설정해준다.
#mysql 설정
spring.datasource.url=jdbc:mysql://localhost:3306/springboot
spring.datasource.username=rg970604
spring.datasource.password=1234
docker exec -i -t mysql_boot bash![](https://velog.velcdn.com/images/rg970604/post/721dca72-f56e-42a9-8f25-23c4f2434ec8/image.png)
프론트엔드 코드추가
// board.css
table {
border-collapse: collapse;
}
table, th, td {
border: 1px solid black;
}
header {
background-color: beige;
padding: 3%;
}
footer {
background-color: beige;
padding: 1%;
text-align: center;
}
#wrap {
padding: 15% 0%;
}
#wrap > * {
margin: 3% 0%;
}
.search {
display: inline;
}
a {
text-decoration: none;
}
// list.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" th:href="@{/css/board.css}">
</head>
<body>
<!-- header 추가 -->
<div th:insert="common/header.html" id="header"></div>
<div id="wrap">
<a th:href="@{/post}">글쓰기</a>
<form action="/board/search" method="GET">
<div class="search">
<input name="keyword" type="text" placeholder="검색어를 입력해주세요">
</div>
<button>검색하기</button>
</form>
<table>
<thead>
<tr>
<th class="one wide">번호</th>
<th class="ten wide">글제목</th>
<th class="two wide">작성자</th>
<th class="three wide">작성일</th>
</tr>
</thead>
<tbody>
<!-- CONTENTS !-->
<tr th:each="board : ${boardList}">
<td>
<span th:text="${board.id}"></span>
</td>
<td>
<a th:href="@{'/post/' + ${board.id}}">
<span th:text="${board.title}"></span>
</a>
</td>
<td>
<span th:text="${board.writer}"></span>
</td>
<td>
<span th:text="${#temporals.format(board.createdDate, 'yyyy-MM-dd HH:mm')}"></span>
</td>
</tr>
</tbody>
</table>
<div>
<span th:each="pageNum : ${pageList}" th:inline="text">
<a th:href="@{'/?page=' + ${pageNum}}">[[${pageNum}]]</a>
</span>
</div>
</div>
<!-- footer 추가 -->
<div th:insert="common/footer.html" id="footer"></div>
</body>
</html>
// detail.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2 th:text="${boardDto.title}"></h2>
<p th:inline="text">작성일 : [[${#temporals.format(boardDto.createdDate, 'yyyy-MM-dd HH:mm')}]]</p>
<p th:text="${boardDto.content}"></p>
<!-- 수정/삭제 -->
<div>
<a th:href="@{'/post/edit/' + ${boardDto.id}}">
<button>수정</button>
</a>
<form id="delete-form" th:action="@{'/post/' + ${boardDto.id}}" method="post">
<input type="hidden" name="_method" value="delete"/>
<button id="delete-btn">삭제</button>
</form>
</div>
<script th:inline="javascript">
/*<![CDATA[*/
var boardDto = /*[[${boardDto}]]*/ "";
/*]]>*/
</script>
<script th:inline="javascript" th:src="@{/js/board.js}"></script>
</body>
</html>
// update.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form th:action="@{'/post/edit/' + ${boardDto.id}}" method="post">
<input type="hidden" name="_method" value="put"/>
<input type="hidden" name="id" th:value="${boardDto.id}"/>
제목 : <input type="text" name="title" th:value="${boardDto.title}"> <br>
작성자 : <input type="text" name="writer" th:value="${boardDto.writer}"> <br>
<textarea name="content" th:text="${boardDto.content}"></textarea><br>
<input type="submit" value="수정">
</form>
</body>
</html>
// write.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/post" method="post">
제목 : <input type="text" name="title"> <br>
작성자 : <input type="text" name="writer"> <br>
<textarea name="content"></textarea><br>
<input type="submit" value="등록">
</form>
</body>
</html>
// footer.html
<footer>
<h4>Footer 입니다</h4>
</footer>
// header.html
<header>
<h1>Header 입니다.</h1>
</header>