๐Ÿ’ป ์ฝ”๋”ฉ ์ผ๊ธฐ : [Spring] '๊ฐ„๋‹จํ•œ ๊ฒŒ์‹œํŒ ๋งŒ๋“ค๊ธฐ' ํŽธ

ybkยท2024๋…„ 5์›” 1์ผ

spring

๋ชฉ๋ก ๋ณด๊ธฐ
23/55
post-thumbnail

๐Ÿ”” '๊ฐ„๋‹จํ•œ ๊ฒŒ์‹œํŒ ๋งŒ๋“ค๊ธฐ'์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž!

๊ฐ„๋‹จํ•œ ๊ฒŒ์‹œํŒ์„ ๋งŒ๋“ค๊ธฐ :
1. ๊ธ€์“ฐ๊ธฐ ๊ธฐ๋Šฅ(C)
2. ์ž‘์„ฑ๋œ ๊ธ€์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋Šฅ(R)
3. ๊ฒŒ์‹œ๋ฌผ ์ˆ˜์ •ํ•˜๋Š” ๊ธฐ๋Šฅ(U)
4. ๊ฒŒ์‹œ๋ฌผ ์‚ญ์ œํ•˜๋Š” ๊ธฐ๋Šฅ(D)


Board ์ž๋ฐ” ๋นˆ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

@Data
public class Board {
    private Integer id;
    private String title;
    private String content;
    private String writer;
    private LocalDateTime inserted;
}

๐Ÿ’Ÿ ๊ธ€์“ฐ๊ธฐ ๊ธฐ๋Šฅ(CREATE)

BoardController

@GetMapping("/add")
public String add() {
    return "board/add";
}

@PostMapping("/add")
public String addPost(Board board, RedirectAttributes redirectAttributes) {
    service.add(board);
    redirectAttributes.addAttribute("id", board.getId());
    return "redirect:/";
}
  • @GetMapping("/add") : localhost:8080/add ๊ฒฝ๋กœ๋กœ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด add() ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉฐ ๊ฒŒ์‹œ๊ธ€์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ทฐ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
  • @PostMapping("/add") : addPost() ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉฐ ๊ฒŒ์‹œ๊ธ€์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์ถ”๊ฐ€๋œ ๊ฒŒ์‹œ๊ธ€์˜ ID๋ฅผ ํฌํ•จํ•œ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•ฉ๋‹ˆ๋‹ค. ex) localhost:8080/board?id=10
  • service.add(board); : ์ „๋‹ฌ๋œ ๊ฒŒ์‹œ๊ธ€ ์ •๋ณด๋ฅผ ๊ฒ€์ฆํ•˜๊ณ  ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

BoardService

public void add(Board board) {
    mapper.insert(board);
}
  • ์ฃผ์–ด์ง„ Borad ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„ Mapper๋ฅผ ํ†ตํ•ด DB์— ์ƒˆ๋กœ์šด ๊ฒŒ์‹œ๊ธ€์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

BoardMapper

@Insert("""
        INSERT INTO board (title, content, writer)
        VALUES (#{title}, #{content}, #{writer})
        """)
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(Board board);
  • ๊ฒŒ์‹œ๊ธ€์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด @Insert ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•˜๊ณ  @Options ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ useGeneratedKeys = true๋กœ ์„ค์ •ํ•˜์—ฌ ์ž๋™ ์ƒ์„ฑ๋œ ํ‚ค(id)๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ๊ฒŒ์‹œ๊ธ€ ์ถ”๊ฐ€ ์š”์ฒญ์„ ํ•˜๋ฉด ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ํ•ด๋‹น ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ์„œ๋น„์Šค ๊ณ„์ธต์„ ๊ฑฐ์ณ์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ƒˆ๋กœ์šด ๊ฒŒ์‹œ๊ธ€์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ณผ์ •์ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ถ”๊ฐ€๋œ ๊ฒŒ์‹œ๊ธ€์€ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž์—๊ฒŒ ์•Œ๋ ค์ง€๊ณ , ์‚ฌ์šฉ์ž๋Š” ์ถ”๊ฐ€๋œ ๊ฒŒ์‹œ๊ธ€์˜ ID๋ฅผ ํฌํ•จํ•œ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋ฉ๋‹ˆ๋‹ค.


๐Ÿ’Ÿ ์ž‘์„ฑ๋œ ๊ธ€์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋Šฅ(R)

โ˜‘๏ธ ๋ชจ๋“  ๊ฒŒ์‹œ๊ธ€์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋Šฅ

BoardController

@GetMapping("/")
public String home(Model model) {
    // ๊ฒŒ์‹œ๋ฌผ ๋ชฉ๋ก ์กฐํšŒ(Select)
    // ๋ชจ๋ธ์— ๋„ฃ๊ณ 
    model.addAttribute("boardList", service.list());
    //jsp๋กœ ํฌ์›Œ๋“œ
    return "board/home";
  • ์„œ๋น„์Šค ๊ณ„์ธต์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ฒŒ์‹œ๋ฌผ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์™€ ์ด๋ฅผ ๋ชจ๋ธ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฒŒ์‹œํŒ ํ™ˆ ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๋ทฐ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

BoardService

public List<Board> list() {
    return mapper.selectAll();
}
  • Borad ๊ฐ์ฒด์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ›์•„ Mapper๋ฅผ ํ†ตํ•ด DB์žˆ๋Š” ๋ชจ๋“  ๊ฒŒ์‹œ๋ฌผ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

BoardMapper

@Select("SELECT * FROM board ORDER BY id DESC")
List<Board> selectAll();
  • DB์˜ ๋ชจ๋“  ๊ฒŒ์‹œ๋ฌผ์„ ์กฐํšŒํ•˜๊ณ  ์ตœ์‹  ๊ฒŒ์‹œ๋ฌผ๋ถ€ํ„ฐ ์ •๋ ฌํ•˜์—ฌ List์— ๋‹ด์•„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ „์ฒด ๊ฒŒ์‹œ๋ฌผ์„ ์กฐํšŒํ•˜๋Š” ์š”์ฒญ์„ ํ•˜๋ฉด, ์„œ๋น„์Šค์˜ list() ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ , ์ด ๋ฉ”์„œ๋“œ๋Š” ๋งคํผ๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ๊ฒŒ์‹œ๋ฌผ์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. ์กฐํšŒ๋œ ๊ฒŒ์‹œ๋ฌผ์€ ์„œ๋น„์Šค๋ฅผ ํ†ตํ•ด ์ปจํŠธ๋กค๋Ÿฌ๋กœ ๋ฐ˜ํ™˜๋˜์–ด ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.


โ˜‘๏ธ ํŠน์ • id๋ฅผ ๋ฐ›์•„ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋Šฅ

BoardController

@GetMapping("/board")
public String view(Integer id, Model model) {
    // ๊ฒŒ์‹œ๋ฌผ ์กฐํšŒ(select) ์กฐํšŒ ๊ฒฐ๊ณผ ๋ชจ๋ธ์— ๋„ฃ๊ณ  jsp๋กœ ํฌ์›Œ๋”ฉ
    Board board = service.get(id);
    model.addAttribute("board", board);
    return "board/view";
}
  • ์„œ๋น„์Šค์—์„œ id๋ฅผ ๋ฐ›์•„์™€ ๋ฐ›์•„์˜จ ๊ฒŒ์‹œ๋ฌผ์„ ๋ชจ๋ธ ์ถ”๊ฐ€ํ•˜๊ณ  ํ•ด๋‹น ์•„์ด๋””์˜ ๊ฒŒ์‹œ๊ธ€์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

BoardService

public Board get(Integer id) {
    return mapper.selectById(id);
}
  • get(Integer id) : ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์€ ID์— ํ•ด๋‹นํ•˜๋Š” ๊ฒŒ์‹œ๋ฌผ์„ ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. ๋งคํผ๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ID๋ฅผ ๊ฐ€์ง„ ๊ฒŒ์‹œ๋ฌผ์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

BoardMapper

@Select("SELECT * FROM board WHERE id = #{id}")
Board selectById(Integer id);
  • ์ฃผ์–ด์ง„ ID์— ํ•ด๋‹นํ•˜๋Š” ๊ฒŒ์‹œ๋ฌผ์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. #{id}๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์€ ID๋ฅผ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ํŠน์ • ID๋ฅผ ๊ฐ€์ง„ ๊ฒŒ์‹œ๋ฌผ์„ ์กฐํšŒํ•˜๋Š” ์š”์ฒญ์„ ํ•˜๋ฉด, ์„œ๋น„์Šค์˜ get() ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ , ์ด ๋ฉ”์„œ๋“œ๋Š” ๋งคํผ๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ๊ฒŒ์‹œ๋ฌผ์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. ์กฐํšŒ๋œ ๊ฒŒ์‹œ๋ฌผ์€ ์„œ๋น„์Šค๋ฅผ ํ†ตํ•ด ์ปจํŠธ๋กค๋Ÿฌ๋กœ ๋ฐ˜ํ™˜๋˜์–ด ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.


๐Ÿ’Ÿ ๊ฒŒ์‹œ๋ฌผ ์‚ญ์ œํ•˜๋Š” ๊ธฐ๋Šฅ(DELETE)

BoardController

@PostMapping("/delete")
public String delete(Integer id) {
    service.remove(id);
    return "redirect:/";
}
  • ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒŒ์‹œ๋ฌผ ์‚ญ์ œ๋ฅผ ์œ„ํ•ด POST์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด delete() ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
  • ์„œ๋น„์Šค์˜ remove(id) ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์ „๋‹ฌ๋ฐ›์€ ID์— ํ•ด๋‹นํ•˜๋Š” ๊ฒŒ์‹œ๊ธ€์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฒŒ์‹œ๋ฌผ ์‚ญ์ œ ํ›„ ํ™ˆํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•ฉ๋‹ˆ๋‹ค.

BoardService

public void remove(Integer id) {
    mapper.deleteById(id);
}
  • ๋งคํผ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ฒŒ์‹œ๋ฌผ์˜ id๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„ ํ•ด๋‹น id์— ํ•ด๋‹นํ•˜๋Š” ๊ฒŒ์‹œ๋ฌผ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

BoardMapper

@Delete("DELETE FROM board WHERE id = #{id}")
int deleteById(Integer id);
  • DELETE ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ์ฃผ์–ด์ง„ id์— ํ•ด๋‹นํ•˜๋Š” ๊ฒŒ์‹œ๋ฌผ์„ DB์—์„œ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ๊ฒŒ์‹œ๋ฌผ ์‚ญ์ œ ์š”์ฒญ์„ ํ•˜๋ฉด ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ํ•ด๋‹น ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ์„œ๋น„์Šค ๊ณ„์ธต์„ ๊ฑฐ์ณ์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ํ•ด๋‹น ๊ฒŒ์‹œ๋ฌผ์ด ์‚ญ์ œ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‚ญ์ œ๋œ ํ›„์—๋Š” ํ™ˆ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋ฉ๋‹ˆ๋‹ค.


๐Ÿ’Ÿ ๊ฒŒ์‹œ๋ฌผ ์ˆ˜์ •ํ•˜๋Š” ๊ธฐ๋Šฅ(UPDATE)

BoardController

    @GetMapping("/modify")
    public String modifyForm(Integer id, Model model) {
        //์กฐํšŒ ํ•ด์„œ ๋ชจ๋ธ์— ๋„ฃ๊ณ 
        model.addAttribute("board", service.get(id));
        //view๋กœ ํฌ์›Œ๋“œ
        return "board/modify";
    }

    @PostMapping("/modify")
    public String modifyPost(Board board, RedirectAttributes redirectAttributes) {
        service.modify(board);
        redirectAttributes.addAttribute("id", board.getId());
        return "redirect:/board"; // ์ˆ˜์ • ๋œ ๊ธ€์„ ๋ณด๋Š” ํ™”๋ฉด์œผ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
    }
  • modifyForm() ๋ฉ”์„œ๋“œ:

    • @GetMapping("/modify"): ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒŒ์‹œ๋ฌผ์„ ์ˆ˜์ •ํ•˜๊ณ ์ž ํ•  ๋•Œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
    • ์ „๋‹ฌ๋œ ๊ฒŒ์‹œ๋ฌผ์˜ ID๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น ๊ฒŒ์‹œ๋ฌผ์„ ์กฐํšŒํ•˜๊ณ , ์ˆ˜์ •์„ ์œ„ํ•œ ํผ์— ์ด ์ •๋ณด๋ฅผ ์ฑ„์›๋‹ˆ๋‹ค.
    • ์ˆ˜์ • ํผ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋ธ์— ์ถ”๊ฐ€ํ•˜๊ณ , "board/modify" ๋ทฐ๋กœ ํฌ์›Œ๋”ฉํ•˜์—ฌ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
  • modifyPost() ๋ฉ”์„œ๋“œ:

    • @PostMapping("/modify"): ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒŒ์‹œ๋ฌผ์„ ์ˆ˜์ •ํ•œ ๋‚ด์šฉ์„ ์ œ์ถœํ•˜๋ฉด ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
    • ์ „๋‹ฌ๋œ ๊ฒŒ์‹œ๋ฌผ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น ๊ฒŒ์‹œ๋ฌผ์„ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
    • ์ˆ˜์ •๋œ ๊ฒŒ์‹œ๋ฌผ์˜ ID๋ฅผ ํฌํ•จํ•œ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•ฉ๋‹ˆ๋‹ค.

BoardService

public void modify(Board board) {
    mapper.update(board);
}
  • ๋งคํผ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ board ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„ ํ•ด๋‹น board ๊ฐ์ฒด์— ํ•ด๋‹นํ•˜๋Š” ๊ฒŒ์‹œ๋ฌผ์„ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

BoardMapper

@Update("""
        UPDATE board 
        SET title = #{title}, content = #{content}, writer = #{writer}
        WHERE id = #{id}
        """)
int update(Board board);
  • ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์€ Board ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น ๊ฒŒ์‹œ๋ฌผ์„ ์ˆ˜์ •ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์„œ๋น„์Šค๋Š” ๊ฒŒ์‹œ๋ฌผ์„ ์ˆ˜์ •ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ์ปจํŠธ๋กค๋Ÿฌ๋Š” ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์„ ๋ฐ›์•„ ํ•ด๋‹น ์š”์ฒญ์— ๋งž๋Š” ์„œ๋น„์Šค ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉฐ, ๋งคํผ๋Š” ์ „๋‹ฌ๋œ ๊ฒŒ์‹œ๋ฌผ ์ •๋ณด๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ํ•ด๋‹น ๊ฒŒ์‹œ๋ฌผ์„ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’Ÿ ์ „์ฒด ์ฝ”๋“œ

BoardController

@Controller
@RequiredArgsConstructor
public class BoardController {

    private final BoardService service;

    @GetMapping("/add")
    public String add() {

        return "board/add";
    }

    @PostMapping("/add")
    public String addPost(Board board, RedirectAttributes redirectAttributes) {
        System.out.println("BoardController.addPost");
        System.out.println("board = " + board);
        service.add(board);
        redirectAttributes.addAttribute("id", board.getId());
        return "redirect:/";
    }

    // /board?id=3
    @GetMapping("/board")
    public String view(Integer id, Model model) {
        // ๊ฒŒ์‹œ๋ฌผ ์กฐํšŒ(select) ์กฐํšŒ ๊ฒฐ๊ณผ ๋ชจ๋ธ์— ๋„ฃ๊ณ  jsp๋กœ ํฌ์›Œ๋”ฉ
        Board board = service.get(id);
        model.addAttribute("board", board);
        return "board/view";
    }

    @GetMapping("/")
    public String home(Model model) {
        // ๊ฒŒ์‹œ๋ฌผ ๋ชฉ๋ก ์กฐํšŒ(Select)
        // ๋ชจ๋ธ์— ๋„ฃ๊ณ 
        model.addAttribute("boardList", service.list());
        //jsp๋กœ ํฌ์›Œ๋“œ
        return "board/home";
    }

    @PostMapping("/delete")
    public String delete(Integer id) {
        service.remove(id);
        return "redirect:/";
    }

    @GetMapping("/modify")
    public String modifyForm(Integer id, Model model) {
        //์กฐํšŒ ํ•ด์„œ
        // ๋ชจ๋ธ์— ๋„ฃ๊ณ 
        model.addAttribute("board", service.get(id));
        //view๋กœ ํฌ์›Œ๋“œ
        return "board/modify";
    }

    @PostMapping("/modify")
    public String modifyPost(Board board, RedirectAttributes redirectAttributes) {
        System.out.println("board = " + board);
        service.modify(board);
        redirectAttributes.addAttribute("id", board.getId());
        return "redirect:/board"; // ๊ธ€์„ ๋ณด๋Š” ํ™”๋ฉด์œผ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
    }

}

BoardService

@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class BoardService {

    private final BoardMapper mapper;

    public void add(Board board) {
        mapper.insert(board);
    }

    public Board get(Integer id) {
        return mapper.selectById(id);
    }

    public List<Board> list() {
        return mapper.selectAll();
    }

    public void remove(Integer id) {
        mapper.deleteById(id);
    }

    public void modify(Board board) {
        mapper.update(board);
    }
}

BoardMapper

@Mapper
public interface BoardMapper {

    @Insert("""
            INSERT INTO board (title, content, writer)
            VALUES (#{title}, #{content}, #{writer})
            """)
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insert(Board board);

    @Select("SELECT * FROM board WHERE id = #{id}")
    Board selectById(Integer id);

    @Select("SELECT * FROM board ORDER BY id DESC")
    List<Board> selectAll();

    @Delete("DELETE FROM board WHERE id = #{id}")
    int deleteById(Integer id);


    @Update("""
            UPDATE board 
            SET title = #{title}, content = #{content}, writer = #{writer}
            WHERE id = #{id}
            """)
    int update(Board board);
}

JSP


hoem(์ฒซ ํ™”๋ฉด)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>home</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

</head>
<body>

<c:import url="/WEB-INF/fragment/navbar.jsp"/>

<div class="container">
    <div class="row justify-content-center">
        <div class="col-6">
            <h3>๊ฒŒ์‹œ๋ฌผ ๋ชฉ๋ก</h3>
            <table class="table">
                <thead>
                <tr>
                    <th style="width: 50px">NO</th>
                    <th>์ œ๋ชฉ</th>
                    <th style="width: 170px">์ž‘์„ฑ์ž</th>
                </tr>
                </thead>
                <tbody class="table-group-divider">
                <c:forEach items="${boardList}" var="board">
                    <c:url value="/board" var="viewLink">
                        <c:param name="id" value="${board.id}"/>
                    </c:url>
                    <tr>
                        <td>${board.id}</td>
                        <td>
                            <a href="${viewLink}">${board.title}</a>
                        </td>
                        <td>${board.writer}</td>
                    </tr>
                </c:forEach>
                </tbody>
            </table>
        </div>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
        crossorigin="anonymous"></script>
</body>
</html>

navbar

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>

<nav class="navbar navbar-expand-lg bg-body-tertiary bg-primary mb-4" data-bs-theme="dark">
    <div class="container">
        <a class="navbar-brand" href="/">BOARD๐Ÿ˜Ž</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
                aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav">
                <li class="nav-item">
                    <a href="/" class="nav-link">
                        ๋ชฉ๋ก
                    </a>
                </li>
                <li class="nav-item">
                    <a href="/add" class="nav-link">
                        ๊ธ€์“ฐ๊ธฐ
                    </a>
                </li>
            </ul>
        </div>
    </div>
</nav>

view(ํ•ด๋‹น id ๊ฒŒ์‹œ๊ธ€ ํ™”๋ฉด)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

</head>
<body>


<c:import url="/WEB-INF/fragment/navbar.jsp"/>

<div class="container">

    <div class="row justify-content-center">
        <div class="col-6">
            <h3>${board.id} ๋ฒˆ ๊ฒŒ์‹œ๋ฌผ</h3>
            <div class="mb-3">
                <label for="inputTitle" class="form-label">
                    ์ œ๋ชฉ
                </label>
                <input id="inputTitle" class="form-control" type="text" value="${board.title}" readonly>
            </div>
            <div class="mb-3">
                <label for="textareaContent" class="form-label">
                    ๋ณธ๋ฌธ
                </label>
                <textarea id="textareaContent" class="form-control" cols="30" rows="10"
                          readonly>${board.content}</textarea>
            </div>
            <div class="mb-3">
                <label for="inputWriter" class="form-label">
                    ์ž‘์„ฑ์ž
                </label>
                <input id="inputWriter" class="form-control" type="text" readonly value="${board.writer}">
            </div>
            <div class="mb-3">
                <label for="inputInserted" class="form-label">
                    ์ž‘์„ฑ์ผ์‹œ
                </label>
                <input id="inputInserted" class="form-control" type="datetime-local" readonly value="${board.inserted}">
            </div>
            <div class="mb-3">
                <button form="formDelete" class="btn btn-danger">์‚ญ์ œ</button>
                <a href="/modify?id=${board.id}" class="btn btn-primary">์ˆ˜์ •</a>
            </div>
        </div>
    </div>
</div>


<div style="display: none">
    <form id="formDelete" action="/delete" method="post" onsubmit="return confirm('์‚ญ์ œ ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?')">
        <input type="hidden" name="id" value="${board.id}">
    </form>
</div>


<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
        crossorigin="anonymous"></script>
</body>
</html>

add(๊ธ€์“ฐ๊ธฐ ํ™”๋ฉด)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>์ถ”๊ฐ€</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

<body>

<c:import url="/WEB-INF/fragment/navbar.jsp"/>

<div class="container">
    <div class="row justify-content-center">
        <div class="col-7">
            <h3 class="mb-4">์ƒˆ ๊ฒŒ์‹œ๋ฌผ ์ž‘์„ฑ</h3>

            <form action="/add" method="post">
                <div class="mb-3">
                    <label for="inputTitle" class="form-label">
                        ์ œ๋ชฉ
                    </label>
                    <input class="form-control" id="inputTitle" type="text" name="title" required>
                </div>
                <div class="mb-3">
                    <label for="textareaContent" class="form-control">
                        ๋ณธ๋ฌธ
                    </label>
                    <textarea class="form-control" id="textareaContent" name="content" cols="30" rows="10"
                              required></textarea>
                </div>
                <div class="mb-3">
                    <label for="inputWriter" class="form-label">
                        ์ž‘์„ฑ์ž
                    </label>
                    <input class="form-control" id="inputWriter" type="text" name="writer" required>
                </div>
                <div class="mb-3">
                    <button class="btn btn-primary btn-lg">์ €์žฅ</button>
                </div>
            </form>
        </div>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
        crossorigin="anonymous"></script>
</body>
</html>

modiy(๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • ํ™”๋ฉด)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>์ˆ˜์ •</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

</head>
<body>
<c:import url="/WEB-INF/fragment/navbar.jsp"/>

<div class="container">
    <div class="row justify-content-center">
        <div class="col-7">

            <h3 class="mb-4">${board.id}๋ฒˆ ๊ฒŒ์‹œ๋ฌผ ์ˆ˜์ •</h3>
            <form action="/modify" method="post">
                <input type="hidden" name="id" value="${board.id}">
                <div class="mb-3">
                    <label for="inputTitle" class="form-label">
                        ์ œ๋ชฉ
                    </label>
                    <input id="inputTitle" class="form-control" type="text" value="${board.title}" name="title"
                           required>
                </div>
                <div class="mb-3">
                    <label for="textareaContent" class="form-label">
                        ๋ณธ๋ฌธ
                    </label>
                    <textarea id="textareaContent" class="form-control" cols="30" rows="10" name="content"
                              required>${board.content}</textarea>
                </div>
                <div class="mb-3">
                    <label for="inputWriter" class="form-label">
                        ์ž‘์„ฑ์ž
                    </label>
                    <input id="inputWriter" class="form-control" type="text" value="${board.writer}" name="writer"
                           required>
                </div>
                <div class="mb-3">
                    <button class="btn btn-secondary">์ˆ˜์ •</button>
                </div>
            </form>
        </div>
    </div>
</div>

<script src=" https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
        crossorigin="anonymous"></script>
</body>
</html>

ํ™”๋ฉด(view)

์ฒซ ํ™”๋ฉด

๊ฒŒ์‹œ๋ฌผ ์ž‘์„ฑ ํ™”๋ฉด

์ œ๋ชฉ ํด๋ฆญ ์‹œ ํ•ด๋‹น ๊ฒŒ์‹œ๋ฌผ๋กœ ๋„˜์–ด๊ฐ€๋Š” ํ™”๋ฉด

profile
๊ฐœ๋ฐœ์ž ์ค€๋น„์ƒ~

0๊ฐœ์˜ ๋Œ“๊ธ€