Search

๊ฒŒ์‹œํŒ ํ”„๋กœ์ ํŠธ

๊ฒŒ์‹œํŒ ํ”„๋กœ์ ํŠธ

โ€ข
ํ”„๋กœ์ ํŠธ
โ—ฆ
build.gradle
โ—ฆ
application.properties
โ—ฆ
๋กœ๊ทธ
โ–ช
โ–ช
โ€ข
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
โ—ฆ
board.sql
โ€ข
์†Œ์Šค์ฝ”๋“œ
โ—ฆ
๋กœ์ง
โ–ช
Board.java
โ–ช
BoardMapper.xml
โ–ช
BoardMapper.java
โ–ช
BoardService.java
โ–ช
BoardServiceImpl.java
โ–ช
BoardController.java
โ–ช
HomeController.java
โ—ฆ
ํ™”๋ฉด
โ–ช
index.html
โ–ช
board
โ€ข
list.html
โ€ข
create.html
โ€ข
detail.html
โ€ข
update.html

ํ”„๋กœ์ ํŠธ

โ€ข
build.gradle
โ€ข
application.properties
โ€ข
๋กœ๊ทธ
โ—ฆ
โ—ฆ

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
๋ณต์‚ฌ

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค

โ€ข
board.sql
-- ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒ์„ฑ 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.java
โ—ฆ
BoardMapper.xml
โ—ฆ
BoardMapper.java
โ—ฆ
BoardService.java
โ—ฆ
BoardServiceImpl.java
โ—ฆ
BoardController.java
โ—ฆ
HomeController.java
โ€ข
ํ™”๋ฉด
โ—ฆ
index.html
โ—ฆ
board
โ–ช
list.html
โ–ช
create.html
โ–ช
detail.html
โ–ช
update.html

๋กœ์ง

โ€ข
Board.java
โ€ข
BoardMapper.xml
โ€ข
BoardMapper.java
โ€ข
BoardService.java
โ€ข
BoardServiceImpl.java
โ€ข
BoardController.java
โ€ข
HomeController.java

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
๋ณต์‚ฌ

ํ™”๋ฉด

โ€ข
index.html
โ€ข
board
โ—ฆ
list.html
โ—ฆ
create.html
โ—ฆ
detail.html
โ—ฆ
update.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>๋ฉ”์ธํ™”๋ฉด</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
๋ณต์‚ฌ