๊ฒ์ํ ํ๋ก์ ํธ
โข
๋ฐ์ดํฐ๋ฒ ์ด์ค
โฆ
โข
์์ค์ฝ๋
โฆ
๋ก์ง
โช
โช
โช
โช
โช
โช
โช
โฆ
ํ๋ฉด
โช
โช
board
โข
โข
โข
โข
ํ๋ก์ ํธ
โข
โข
build.gradle
plugins {
id 'java'
id 'war'
id 'org.springframework.boot' version '3.5.9'
id 'io.spring.dependency-management' version '1.1.7'
}
group = 'com.aloha'
version = '0.0.1-SNAPSHOT'
description = '๊ฒ์ํ ํ๋ก์ ํธ'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(23)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.5'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.5'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
// log4j2 ๋ก๊น
๋ผ์ด๋ธ๋ฌ๋ฆฌ
// implementation 'org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16'
// P6Spy ๋ก๊น
๋ผ์ด๋ธ๋ฌ๋ฆฌ
implementation 'p6spy:p6spy:3.9.1'
}
tasks.named('test') {
useJUnitPlatform()
}
Java
๋ณต์ฌ
application.properties
spring.application.name=board
# ๋ฐ์ดํฐ ์์ค - MySQL
# ๊ธฐ๋ณธ ๋ฐ์ดํฐ ์์ค
# spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# spring.datasource.url=jdbc:mysql://127.0.0.1:3306/aloha?serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&useSSL=false&autoReconnection=true&autoReconnection=true
# log4j2
# spring.datasource.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
# spring.datasource.url=jdbc:log4jdbc:mysql://localhost:3306/aloha?serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&useSSL=false&autoReconnection=true&autoReconnection=true
# p6spy
spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver
spring.datasource.url=jdbc:p6spy:mysql://localhost:3306/aloha?serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&useSSL=false&autoReconnection=true&autoReconnection=true
spring.datasource.username=aloha
spring.datasource.password=123456
# Mybatis ์ค์
# Mybatis ์ค์ ๊ฒฝ๋ก : ~/resources/mybatis-config.xml
# mybatis.config-location=classpath:mybatis-config.xml
# ์ปฌ๋ผ๋ช
์ ๋ณ์๋ช
์ผ๋ก ์๋๋งคํ : board_no โก boardNo
mybatis.configuration.map-underscore-to-camel-case=true
# resultType ์์ฑ์์ dto ๊ฐ์ฒด (ํจํค์ง.ํด๋์ค๋ช
) โก (ํด๋์ค๋ช
)
mybatis.type-aliases-package=com.aloha.board.dto
# Mybatis ๋งคํผ ํ์ผ ๊ฒฝ๋ก : ~/๋ฉ์ธํจํค์ง/mapper/**Mapper.xml
mybatis.mapper-locations=classpath:mybatis/mapper/**/**.xml
# ๋ก๊ทธ ๋ ๋ฒจ ์ค์
# level : TRACE, DEBUG, INFO, WARN, ERROR
logging.level.com.aloha.board=INFO
# logging.level.com.aloha.board.mapper=INFO
# ANSI ์ปฌ๋ฌ ์ถ๋ ฅ ์ค์
spring.output.ansi.enabled=ALWAYS
Java
๋ณต์ฌ
๋ก๊ทธ
โข
โข
spy.properties
# P6Spy์์ ์ฌ์ฉํ ๋ชจ๋(๋ก๊ทธ ํฉํ ๋ฆฌ) ์ง์
# SQL ์คํ ์ ๋ณด๋ฅผ ์์งํ์ฌ ๋ก๊ทธ๋ก ์ถ๋ ฅํ๋ ํต์ฌ ๋ชจ๋
modulelist=com.p6spy.engine.logging.P6LogFactory
# SQL ๋ก๊ทธ ์ถ๋ ฅ ํฌ๋งท ์ง์
# MultiLineFormat โ ์ค๋ฐ๊ฟ + ๋ค์ฌ์ฐ๊ธฐ ๋ ๊ฐ๋
์ฑ ์ข์ SQL ๋ก๊ทธ ์ถ๋ ฅ
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat
# ๋ก๊ทธ ์ถ๋ ฅ ๋ฐฉ์ ์ง์
# Slf4JLogger โ SLF4J๋ฅผ ํตํด logback / log4j2 ์ค์ ์ ๊ทธ๋๋ก ์ฌ์ฉ
appender=com.p6spy.engine.spy.appender.Slf4JLogger
Java
๋ณต์ฌ
๋ฐ์ดํฐ๋ฒ ์ด์ค
โข
-- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ฑ
CREATE DATABASE IF NOT EXISTS aloha;
Java
๋ณต์ฌ
board.sql
-- ์ธ๋ํค ๋ฌด์
SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS board;
-- ๊ฒ์ํ ํ
์ด๋ธ ์์ฑ
CREATE TABLE `board` (
`no` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
`id` varchar(64) DEFAULT NULL UNIQUE,
`title` varchar(100) NOT NULL,
`writer` varchar(100) NOT NULL,
`content` text,
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- ์ํ ๋ฐ์ดํฐ
TRUNCATE Table board;
INSERT INTO board (id, title, writer, content)
VALUES
( UUID(), '์ ๋ชฉ1', '์์ฑ์1', '๋ด์ฉ1'),
( UUID(), '์ ๋ชฉ2', '์์ฑ์2', '๋ด์ฉ2'),
( UUID(), '์ ๋ชฉ3', '์์ฑ์3', '๋ด์ฉ3'),
( UUID(), '์ ๋ชฉ4', '์์ฑ์4', '๋ด์ฉ4'),
( UUID(), '์ ๋ชฉ5', '์์ฑ์5', '๋ด์ฉ5')
;
-- ์ธ๋ํค ํ์ฑํ
SET FOREIGN_KEY_CHECKS=1;
Java
๋ณต์ฌ
์์ค์ฝ๋
โข
๋ก์ง
โฆ
โฆ
โฆ
โฆ
โฆ
โฆ
โฆ
โข
ํ๋ฉด
โฆ
โฆ
board
โช
โช
โช
โช
๋ก์ง
โข
โข
โข
โข
โข
โข
โข
Board.java
@Data
public class Board {
private Integer no;
private String id;
private String title;
private String writer;
private String content;
private Date createdAt;
private Date updatedAt;
public Board() {
this.id = UUID.randomUUID().toString();
}
}
Java
๋ณต์ฌ
BoardMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace="๋งคํผ ์ธํฐํ์ด์ค ๊ฒฝ๋ก" -->
<mapper namespace="com.aloha.board.mapper.BoardMapper">
<!-- ๊ฒ์๊ธ ๋ชฉ๋ก -->
<!-- <select id="list" resultType="com.aloha.mybatis.dto.Board"> -->
<select id="list" resultType="Board">
SELECT *
FROM board
ORDER BY created_at DESC
</select>
<!-- ๊ฒ์๊ธ ์กฐํ -->
<select id="select" resultType="Board">
SELECT *
FROM board
WHERE no = #{no}
</select>
<!-- ๊ฒ์๊ธ ๋ฑ๋ก -->
<insert id="insert">
INSERT INTO board ( id, title, writer, content )
VALUES ( #{id}, #{title}, #{writer}, #{content} )
</insert>
<!-- ๊ฒ์๊ธ ์์ -->
<update id="update">
UPDATE board
SET title = #{title}
,writer = #{writer}
,content = #{content}
WHERE no = #{no}
</update>
<!-- ๊ฒ์๊ธ ์ญ์ -->
<delete id="delete">
DELETE FROM board
WHERE no = #{no}
</delete>
</mapper>
XML
๋ณต์ฌ
BoardMapper.java
@Mapper
public interface BoardMapper {
// ๊ฒ์๊ธ ๋ชฉ๋ก
List<Board> list() throws Exception;
// ๊ฒ์๊ธ ์กฐํ
Board select(Integer no) throws Exception;
// ๊ฒ์๊ธ ๋ฑ๋ก
int insert(Board board) throws Exception;
// ๊ฒ์๊ธ ์์
int update(Board board) throws Exception;
// ๊ฒ์๊ธ ์ญ์
int delete(Integer no) throws Exception;
}
Java
๋ณต์ฌ
BoardService.java
public interface BoardService {
// ๊ฒ์๊ธ ๋ชฉ๋ก
List<Board> list() throws Exception;
// ๊ฒ์๊ธ ์กฐํ
Board select(Integer no) throws Exception;
// ๊ฒ์๊ธ ๋ฑ๋ก
boolean insert(Board board) throws Exception;
// ๊ฒ์๊ธ ์์
boolean update(Board board) throws Exception;
// ๊ฒ์๊ธ ์ญ์
boolean delete(Integer no) throws Exception;
}
Java
๋ณต์ฌ
BoardServiceImpl.java
@Service
@RequiredArgsConstructor
public class BoardServiceImpl implements BoardService {
private final BoardMapper boardMapper;
@Override
public List<Board> list() throws Exception {
List<Board> list = boardMapper.list();
return list;
}
@Override
public Board select(Integer no) throws Exception {
Board board = boardMapper.select(no);
return board;
}
@Override
public boolean insert(Board board) throws Exception {
int result = boardMapper.insert(board);
return result > 0;
}
@Override
public boolean update(Board board) throws Exception {
int result = boardMapper.update(board);
return result > 0;
}
@Override
public boolean delete(Integer no) throws Exception {
int result = boardMapper.delete(no);
return result > 0;
}
}
Java
๋ณต์ฌ
BoardController.java
/**
* [GET] - /board/list : ๊ฒ์๊ธ ๋ชฉ๋ก ํ๋ฉด
* [GET] - /board/detail : ๊ฒ์๊ธ ์กฐํ ํ๋ฉด
* [GET] - /board/create : ๊ฒ์๊ธ ๋ฑ๋ก ํ๋ฉด
* [POST] - /board/create : ๊ฒ์๊ธ ๋ฑ๋ก ์ฒ๋ฆฌ
* [GET] - /board/updatee : ๊ฒ์๊ธ ์์ ํ๋ฉด
* [POST] - /board/update : ๊ฒ์๊ธ ์์ ์ฒ๋ฆฌ
* [POST] - /board/delete : ๊ฒ์๊ธ ์ญ์ ์ฒ๋ฆฌ
*/
@Slf4j // ๋ก๊ทธ ์ด๋
ธํ
์ด์
@Controller // ์ปจํธ๋กค๋ฌ ๋น์ผ๋ก ๋ฑ๋ก
@RequestMapping("/board") // ํด๋ ์ค ๋ ๋ฒจ ์์ฒญ ๊ฒฝ๋ก ๋งคํ
@RequiredArgsConstructor
public class BoardController {
private final BoardService boardService;
/**
* ๊ฒ์๊ธ ๋ชฉ๋ก ํ๋ฉด
* @param model
* @return
* @throws Exception
*/
@GetMapping("/list")
public String list(Model model) throws Exception {
// ๋ฐ์ดํฐ ์์ฒญ
List<Board> list = boardService.list();
// ๋ชจ๋ธ ๋ฑ๋ก
model.addAttribute("list", list);
// ๋ทฐ ์ง์
return "board/list";
}
/**
* ๊ฒ์๊ธ ์กฐํ ํ๋ฉด
* - /board/detail?no=๐
* @param no
* @param model
* @return
* @throws Exception
*/
@GetMapping("/detail")
public String detail(
@RequestParam("no") Integer no,
Model model
) throws Exception {
// ๋ฐ์ดํฐ ์์ฒญ
Board board = boardService.select(no);
// ๋ชจ๋ธ ๋ฑ๋ก
model.addAttribute("board", board);
// ๋ทฐ ์ง์
return "board/detail";
}
/**
* ๊ฒ์๊ธ ๋ฑ๋ก ํ๋ฉด
* @return
*/
@GetMapping("/create")
public String create() {
return "board/create";
}
/**
* ๊ฒ์๊ธ ๋ฑ๋ก ์ฒ๋ฆฌ
* @param board
* @return
* @throws Exception
*/
@PostMapping("/create")
public String create(Board board) throws Exception {
// ๋ฐ์ดํฐ ์์ฒญ
boolean result = boardService.insert(board);
// ๋ฆฌ๋ค์ด๋ ํธ
// โญ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ฑ๊ณต
if( result )
return "redirect:/board/list";
// โ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์คํจ
return "redirect:/board/create?error";
}
/**
* ๊ฒ์๊ธ ์์ ํ๋ฉด
* @param no
* @param model
* @return
* @throws Exception
*/
@GetMapping("/update")
public String update(
@RequestParam("no") Integer no,
Model model
) throws Exception {
Board board = boardService.select(no);
model.addAttribute("board", board);
return "board/update";
}
/**
* ๊ฒ์๊ธ ์์ ์ฒ๋ฆฌ
* @param board
* @return
* @throws Exception
*/
@PostMapping("/update")
public String update(Board board) throws Exception {
boolean result = boardService.update(board);
if( result )
return "redirect:/board/list";
int no = board.getNo();
return "redirect:/board/update?no=" + no + "&error";
}
/**
* ๊ฒ์๊ธ ์ญ์ ์ฒ๋ฆฌ
* @param no
* @return
* @throws Exception
*/
@PostMapping("/delete")
public String delete(@RequestParam("no") Integer no) throws Exception {
boolean result = boardService.delete(no);
if( result )
return "redirect:/board/list";
return "redirect:/board/update?no=" + no + "&error";
}
}
Java
๋ณต์ฌ
HomeController.java
@Slf4j
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
log.info("๋ฉ์ธ ํ๋ฉด");
return "index";
}
}
Java
๋ณต์ฌ
ํ๋ฉด
โข
โข
board
โฆ
โฆ
โฆ
โฆ
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>๋ฉ์ธํ๋ฉด</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<main>
<div class="px-4 py-5 my-5 text-center">
<img class="d-block mx-auto mb-4" src="/img/logo.png" alt="" width="100" height="100">
<h1 class="display-5 fw-bold text-body-emphasis">๊ฒ์ํ ํ๋ก์ ํธ</h1>
<div class="col-lg-6 mx-auto">
<p class="lead mb-4">
<ol class="list-group list-group-numbered">
<li class="list-group-item">Spring Boot</li>
<li class="list-group-item">MySQL</li>
<li class="list-group-item">MyBatis</li>
<li class="list-group-item">Thymeleaf</li>
<li class="list-group-item">Bootstrap</li>
</ol>
</p>
<div class="d-grid gap-2 d-sm-flex justify-content-sm-center">
<a href="/board/list" class="btn btn-primary btn-lg px-4 gap-3">๊ฒ์ํ</a>
<a href="/board/create" class="btn btn-outline-secondary btn-lg px-4">๋ฑ๋กํ๊ธฐ</a>
</div>
</div>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
HTML
๋ณต์ฌ
board
list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>๊ฒ์ํ ํ๋ก์ ํธ</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<main>
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-12">
<h1 class="text-center">๊ฒ์๊ธ ๋ชฉ๋ก</h1>
<div class="d-flex justify-content-end">
<a href="/board/create" class="btn btn-primary">๊ธ์ฐ๊ธฐ</a>
</div>
<table class="table table-bordered table-striped table-hover table-responsive mt-3 text-center">
<colgroup>
<col class="col-1"> <!-- ๋ฒํธ -->
<col class="col-3"> <!-- ์ ๋ชฉ -->
<col class="col-2"> <!-- ์์ฑ์ -->
<col class="col-2"> <!-- ๋ฑ๋ก์ผ์ -->
<col class="col-2"> <!-- ์์ ์ผ์ -->
</colgroup>
<tr class="table-dark">
<th width="150">๋ฒํธ</th>
<th width="300">์ ๋ชฉ</th>
<th>์์ฑ์</th>
<th>๋ฑ๋ก์ผ์</th>
<th>์์ ์ผ์</th>
</tr>
<th:block th:if="${ list == null || list.isEmpty() }">
<tr>
<td colspan="5">์กฐํ๋ ๋ฐ์ดํฐ๊ฐ ์์ต๋๋ค.</td>
</tr>
</th:block>
<th:block th:each="board : ${list}">
<tr class="align-middle">
<td th:text="${board.no}">๋ฒํธ</td>
<td class="text-start">
<a th:href="|/board/detail?no=${board.no}|"
th:text="${board.title}">์ ๋ชฉ</a>
</td>
<td th:text="${board.writer}">์์ฑ์</td>
<td>
<span th:text="${ #dates.format( board.createdAt, 'yyyy-MM-dd HH:mm:ss' ) }">
๋ฑ๋ก์ผ์
</span>
</td>
<td>
<span th:text="${ #dates.format( board.updatedAt, 'yyyy-MM-dd HH:mm:ss' ) }">
์์ ์ผ์
</span>
</td>
</tr>
</th:block>
</table>
</div>
</div>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Java
๋ณต์ฌ
create.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>๊ฒ์ํ ํ๋ก์ ํธ</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<main>
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-12 col-md-10 col-lg-6">
<h1 class="text-center">๊ฒ์๊ธ ๋ฑ๋ก</h1>
<form action="/board/create" method="post">
<div class="mb-3">
<label for="" class="form-label">์ ๋ชฉ</label>
<input type="text" class="form-control" name="title" id="title"
aria-describedby="helpTitle" placeholder="์ ๋ชฉ์ ์
๋ ฅํด์ฃผ์ธ์" />
<small id="helpTitle" class="form-text text-muted">์ ๋ชฉ์ ์
๋ ฅํด์ฃผ์ธ์</small>
</div>
<div class="mb-3">
<label for="" class="form-label">์์ฑ์</label>
<input type="text" class="form-control" name="writer" id="writer"
aria-describedby="helpWriter" placeholder="์์ฑ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์" />
<small id="helpWriter" class="form-text text-muted">์์ฑ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์</small>
</div>
<div class="mb-3">
<label for="" class="form-label">๋ด์ฉ</label>
<textarea class="form-control" name="content" id="content" rows="5"></textarea>
</div>
<div class="d-grid gap-2">
<button type="submit" class="btn btn-primary">๋ฑ๋ก</button>
</div>
</form>
</div>
</div>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
HTML
๋ณต์ฌ
detail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>๊ฒ์ํ ํ๋ก์ ํธ</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<main>
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-12 col-md-10 col-lg-6">
<h1 class="text-center">๊ฒ์๊ธ ์กฐํ</h1>
<form action="/board/create" method="post" th:object="${board}">
<div class="mb-3">
<label for="" class="form-label">์ ๋ชฉ</label>
<input type="text" class="form-control" th:field="*{title}"
aria-describedby="helpTitle" placeholder="์ ๋ชฉ์ ์
๋ ฅํด์ฃผ์ธ์"
readonly
/>
</div>
<div class="mb-3">
<label for="" class="form-label">์์ฑ์</label>
<input type="text" class="form-control" th:field="*{writer}"
aria-describedby="helpWriter" placeholder="์์ฑ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์"
readonly
/>
</div>
<div class="mb-3">
<label for="" class="form-label">๋ด์ฉ</label>
<textarea class="form-control" th:field="*{content}" rows="5" readonly></textarea>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-center">
<button type="button" class="btn btn-outline-primary w-100" onclick="moveList()">๋ชฉ๋ก</button>
<button type="button" class="btn btn-primary w-100" onclick="moveUpdate()">์์ </button>
</div>
</form>
</div>
</div>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
<script>
// ๐ฉโ๐ป ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ
let no = '[[${board.no}]]'
// ๋ชฉ๋ก ํ๋ฉด ์ด๋
function moveList() {
location.href = '/board/list'
}
// ์์ ํ๋ฉด ์ด๋
function moveUpdate() {
location.href = '/board/update?no=' + no
}
</script>
</body>
</html>
HTML
๋ณต์ฌ
update.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>๊ฒ์ํ ํ๋ก์ ํธ</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<main>
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-12 col-md-10 col-lg-6">
<h1 class="text-center">๊ฒ์๊ธ ์์ </h1>
<form id="form" action="/board/update" method="post" th:object="${board}">
<input type="hidden" th:field="*{no}">
<div class="mb-3">
<label for="" class="form-label">์ ๋ชฉ</label>
<input type="text" class="form-control" th:field="*{title}"
aria-describedby="helpTitle" placeholder="์ ๋ชฉ์ ์
๋ ฅํด์ฃผ์ธ์"
/>
</div>
<div class="mb-3">
<label for="" class="form-label">์์ฑ์</label>
<input type="text" class="form-control" th:field="*{writer}"
aria-describedby="helpWriter" placeholder="์์ฑ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์"
/>
</div>
<div class="mb-3">
<label for="" class="form-label">๋ด์ฉ</label>
<textarea class="form-control" th:field="*{content}" rows="5"></textarea>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-center mt-2">
<button type="submit" class="btn btn-primary w-100">์์ </button>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-center mt-2">
<button type="button" class="btn btn-outline-primary w-100" onclick="moveList()">๋ชฉ๋ก</button>
<button type="button" class="btn btn-outline-danger w-100" onclick="actionDelete()">์ญ์ </button>
</div>
</form>
</div>
</div>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
<script>
// ๐ฉโ๐ป ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ
let no = '[[${board.no}]]'
// ํผ
let $form = document.getElementById("form")
// ๋ชฉ๋ก ํ๋ฉด ์ด๋
function moveList() {
location.href = '/board/list'
}
// ์ญ์ ์์ฒญ
function actionDelete() {
let check = confirm('์ ๋ง๋ก ์ญ์ ํ์๊ฒ ์ต๋๊น?')
if( check ) {
$form.action = '/board/delete'
$form.submit()
}
}
</script>
</body>
</html>
HTML
๋ณต์ฌ








