IT/development

[springBoot/html] table๊ฐ’ ๋ณ€๊ฒฝ ํ›„ DB update(feat.contenteditable)

์•Œ ์ˆ˜ ์—†๋Š” ์‚ฌ์šฉ์ž 2022. 12. 17.

๋ชฉ์ฐจ

    ํ˜„์žฌ ๋‚ด๋ถ€ ํ”„๋กœ์ ํŠธ ์ง„ํ–‰ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ ์ค‘ ์•„๋ž˜์™€ ๊ฐ™์€ ์š”๊ตฌ์‚ฌํ•ญ์ด ์žˆ์–ด์„œ ๊ตฌํ˜„์„ ํ–ˆ๊ณ  ์ด๋ฅผ ๊ธฐ๋กํ•œ๋‹ค.

    ํ˜„์žฌ ๊ฐœ๋ฐœํ•˜๋ฉฐ ๋‚œ์ด๋„์— ์ƒ๊ด€์—†์ด ๊ธฐ๋ก์„ ํ•˜๊ณ  ์žˆ๋Š”๋ฐ ์ด๋Š” ๋‚˜์ค‘์— ๋ถ„๋ช… ๋‚˜์˜ ์ข‹์€ ์ž์‚ฐ์ด ๋ ๊ฑฐ๋ผ ๋ฏฟ๋Š”๋‹ค.

    ๋ˆ„๊ตฐ๊ฐ€์—๊ฒ ์‰ฌ์šด ์ผ์ด ๋˜ ๋ˆ„๊ตฐ๊ฐ€์—๊ฒ ์ขŒ์ ˆ๊ฐ์„ ์ค„ ์ˆ˜๋„ ์žˆ๊ธฐ์— ์ขŒ์ ˆ์„ ์ค„์ด๊ณ  ์ž์‹ ๊ฐ์„ ๋Š˜๋ฆฌ๊ธฐ ์œ„ํ•จ์ด๋‹ค.

    ์ฒ˜์Œ๋ถ€ํ„ฐ ์ž˜ํ•˜๋Š” ์‚ฌ๋žŒ๋„ ๋ฌผ๋ก  ์žˆ์„ ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ ๊ทธ๋Ÿฐ์‚ฌ๋žŒ์ด ๊ทธ๋ ‡๊ฒŒ ๋งŽ์ง€ ์•Š๋‹ค๊ณ  ๋ณธ๋‹ค.

    ์ฒ˜์Œ์—” ์–ด๋ ค์› ๋˜ ๊ฒŒ ํ•ด๋ณด๋ฉด ๋‚˜์ค‘์— ์‰ฌ์šด๊ฒŒ ๋œ๋‹ค.

    ๊ตฌ๊ธ€์— ์กด์žฌํ•˜๋ฉด ์•ˆํ•ด๋ด์„œ ์–ด๋ ค์šด ๊ฒƒ์ด์ง€ ๋ชปํ•  ๊ฑด ์—†๋‹ค.

    ๊ทธ๋ฆฌ๊ณ  ๊ตฌ๊ธ€์— ์—†์–ด๋„ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ”„๋กœ๋‹ค.(๊ตฌ๊ธ€์— ์—†์œผ๋ฉด ์‹œ๊ฐ„์ด ๋” ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๊ฒ ์ง€)

    ๋‚œ ์•„์ง ๋ถ€์กฑํ•œ ์ง์žฅ์ธ ๊ฐœ๋ฐœ์ž์ด๊ธฐ์— ํ‰๋ฒ”ํ•œ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๊ธฐ์œ„ํ•ด ๋Š์ž„์—†์ด ๊ธฐ๋กํ•˜๊ณ  ๊ณต๋ถ€ํ•  ๊ฒƒ์ด๋‹ค.


    ์š”๊ตฌ์‚ฌํ•ญ์€ ๊ด€๋ฆฌ์žํŽ˜์ด์ง€์—์„œ ๊ทธ๋ฆฌ๋“œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ๋œ๋‹ค.

    ๊ธฐ์กด์— ํ•ด์™”๋˜ ๋ฐ์ดํ„ฐ์˜ ํ‚ค๊ฐ’์œผ๋กœ ์ˆ˜์ • ํŽ˜์ด์ง€์—์„œ ์ˆ˜์ •์„ ํ•˜๋Š” ๋ฐฉ์‹์ด ์•„๋‹ˆ๋ผ ๊ทธ๋ฆฌ๋“œ ๋‚ด์—์„œ ์ธ๋ผ์ธ์œผ๋กœ ์ˆ˜์ •์„ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๊ธฐ๋Šฅ์ด๋‹ค.

     

    jqGrid Loading Data - Inline Editing with on Row Click

     

    www.guriddo.net

    ๊ทธ๋ฆฌ๋“œ์˜ ํ–‰ ์„ ํƒ ํ›„ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด DB์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ˜์˜์ด ๋˜์–ด์•ผ ํ•œ๋‹ค.

    ํ•ด๋ณธ์  ์—†๋Š” ์ด ๊ธฐ๋Šฅ์„ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด ๋ ๊นŒ?์—ฌ๋Ÿฌ ๊ณ ๋ฏผ ๋์— ์•„๋ž˜์˜ ํ”„๋กœ์„ธ์Šค ์ •์˜๋ฅผ ๋‚ด๋ ธ๋‹ค.


    1. ํ™”๋ฉด๋‹จ์—์„œ๋Š” ํ…Œ์ด๋ธ”์˜ td์š”์†Œ๋ฅผ ํŽธ์ง‘ํ•œ๋‹ค.

    2. ์ €์žฅ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ table tr์„ ๋ฃจํ”„ ๋Œ๋ ค ์ด๋ฅผ ์ €์žฅํ•œ ๋‹ค์Œ ์„œ๋ฒ„๋กœ ์ „์†กํ•œ๋‹ค.

    3. ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์„œ ์—ฌ๋Ÿฌ๋ฒˆ DB ์—…๋ฐ์ดํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.

    ์ด ๋•Œ ์—ฌ๋Ÿฌ๋ฒˆ ์—…๋ฐ์ดํŠธ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด java๋‹จ์—์„œ ์—…๋ฐ์ดํŠธ๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ๊ณผ mybatis์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์žˆ๋Š”๋ฐ ๋‚œ ํ›„์ž๋ฅผ ํƒํ–ˆ๋‹ค.

    ์ด๋ฅผ ์œ„ํ•ด์„  ์•„๋ž˜์ฒ˜๋Ÿผ ํ”„๋กœํผํ‹ฐ ์ˆ˜์ •์ด ํ•„์š”ํ•˜๋‹ค.

    #mariadb
    spring.datasource.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
    #allowMultiQueries=true ์ด๋ ‡๊ฒŒ ์„ค์ •์„ ๊ผญ ํ•ด์•ผ ํ•œ๋‹ค.
    spring.datasource.url=jdbc:log4jdbc:mariadb://localhost:3307/test?characterEncoding=UTF-8&allowMultiQueries=true
    spring.datasource.username=test
    spring.datasource.password=1234
    
    mybatis.mapper-locations=mybatis-mapper/**/*.xml

    contenteditable

    ๊ตฌ๊ธ€๋ง ๊ฒฐ๊ณผ html์˜ contenteditable์†์„ฑ์„ ์ด์šฉํ•˜๋ฉด ์ž…๋ ฅํƒœ๊ทธ(input, textarea ๋“ฑ)๊ฐ€ ์•„๋‹Œ ํƒœ๊ทธ๋ฅผ ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค. ์ด๋†ˆ์„ ์ด์šฉํ•  ๊ฒƒ์ด๋‹ค.

    ์•„๋ž˜์—์„œ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅํ•˜๋‹ค.

    See the Pen Untitled by SangYeop Lee (@devLsy) on CodePen.

    ์ฝ”๋“œ๋ฅผ ์น˜๊ธฐ์—” ๊ท€์ฐฎ์ง€๋งŒ ์ •ํ™•ํ•œ ์˜ˆ์ œ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด์„œ ์ฝ”๋“œ๋ฅผ ์น˜๊ฒ ๋‹ค.

    ์‹œ๊ฐ„๊ด€๊ณ„์ƒ ํ™”๋ฉด ๋””์ž์ธ์€ ์—†๋‹ค. ๐Ÿ˜…

    ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ ํ›„ ๊ฐ„๋‹จํ•˜๊ฒŒ board ํ…Œ์ด๋ธ”์„ ํ•˜๋‚˜ ๋งŒ๋“ค์—ˆ๊ณ  ๋ชฉ๋ก ์กฐํšŒ, ๋“ฑ๋ก, ๋‹ค๊ฑด ์ˆ˜์ •๋งŒ ๊ตฌํ˜„ํ•˜๊ฒ ๋‹ค.

    CREATE TABLE `study_board`(
                              `board_seq` bigint auto_increment,
                              `title` varchar (30),
                              `contents` varchar (100),
                              `name` varchar (30),
                              `reg_date` timestamp,
                              `update_date` timestamp,
                              primary key(board_seq)
    );

    BoardVo

    package study.ex1.vo;
    
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter @Setter
    public class BoardVo {
    
        private Long boardSeq;
        private String title;
        private String contents;
        private String name;
        private String regDate;
        private String updateDate;
    }

    mapper 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">
    <mapper namespace="study.ex1.mapper.BoardMapper">
        <resultMap id="boardMap" type="study.ex1.vo.BoardVo">
            <id column="board_seq" property="boardSeq"/>
            <result column="title" property="title"/>
            <result column="contents" property="contents"/>
            <result column="name" property="name"/>
            <result column="reg_date" property="regDate"/>
            <result column="update_date" property="updateDate"/>
        </resultMap>
            
        <!-- ์›๋ž˜๋Š” ์กฐํšŒ ์‹œ *๋Š” ์ง€์–‘ํ•ด์•ผ ํ•˜์ง€๋งŒ ์˜ˆ์ œ๋‹ˆ๊นŒ *๋กœ ํ•จ -->
        <select id="findContentsList" resultMap="boardMap">
            SELECT * FROM study_board
        </select>
    
        <!-- ๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก -->
        <insert id="insertContents" parameterType="study.ex1.vo.BoardVo">
            INSERT INTO study_board
            (
                  title
                 ,contents
                 ,name
                 ,reg_date
                 ,update_date
            )
            VALUES
            (
                 #{title}
                ,#{contents}
                ,#{name}
                ,SYSDATE()
                ,SYSDATE()
            )
        </insert>
    
        <!-- ๋‹ค์ค‘ ์—…๋ฐ์ดํŠธ -->
        <update id="updateContentsList" parameterType="list">
            <foreach collection="list" item="item" index="index" separator=";">
                UPDATE study_board
                SET   title     = #{item.title}
                     ,contents  = #{item.contents}
                     ,name      = #{item.name}
                     ,update_date = SYSDATE()
                WHERE board_seq = #{item.boardSeq}
            </foreach>
        </update>
                                
    </mapper>

    mapper interface

    package study.ex1.mapper;
    
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Select;
    import org.springframework.stereotype.Repository;
    import study.ex1.vo.BoardVo;
    
    import java.util.List;
    
    @Repository @Mapper
    public interface BoardMapper {
    
        //๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ์กฐํšŒ
        List<BoardVo> findContentsList();
        //๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก
        void insertContents(BoardVo boardVo);
        //๊ฒŒ์‹œ๊ธ€ ๋ฆฌ์ŠคํŠธ ์—…๋ฐ์ดํŠธ
        void updateContentsList(List<BoardVo> boardVoList);
    }

    service

    package study.ex1.service;
    
    import lombok.RequiredArgsConstructor;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    import study.ex1.mapper.BoardMapper;
    import study.ex1.vo.BoardVo;
    
    import java.util.List;
    
    @Service
    @Transactional(readOnly = true)
    @RequiredArgsConstructor
    public class BoardService {
    
        private final BoardMapper boardMapper;
    
        /**
         * ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ์กฐํšŒ
         * @return
         */
        public List<BoardVo> findContentsList() {
            return boardMapper.findContentsList();
        }
    
        /**
         * ๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก
         * @param boardVo
         */
        @Transactional
        public void insertContents(BoardVo boardVo) throws Exception{
            boardMapper.insertContents(boardVo);
        }
    
        /**
         * ๊ฒŒ์‹œ๊ธ€ ๋‹ค๊ฑด ์ˆ˜์ •
         * @param boardVoList
         */
        @Transactional
        public void updateContentsList(List<BoardVo> boardVoList) throws Exception{
            boardMapper.updateContentsList(boardVoList);
        }
    }

    jUnit ๋“ฑ๋ก, ์กฐํšŒ, ์ˆ˜์ • ํ…Œ์ŠคํŠธ

    package study.ex1.service;
    
    import lombok.extern.slf4j.Slf4j;
    import org.junit.jupiter.api.DisplayName;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.annotation.Commit;
    import org.springframework.transaction.annotation.Transactional;
    import study.ex1.vo.BoardVo;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import static org.junit.jupiter.api.Assertions.*;
    
    @SpringBootTest
    @Slf4j
    @Transactional
    class BoardServiceTest {
    
        @Autowired BoardService boardService;
    
        @Test
        @DisplayName("๊ฒŒ์‹œ๊ธ€๋“ฑ๋ก")
        @Commit
        public void ๊ฒŒ์‹œ๊ธ€๋“ฑ๋ก() throws Exception {
            for (int i = 0; i < 11; i++) {
                BoardVo boardVo = new BoardVo();
                boardVo.setTitle("์ œ๋ชฉ : " + i);
                boardVo.setContents("๋‚ด์šฉ : " + i);
                boardVo.setName("์•„์ด์–ธ๋งจ");
    
                boardService.insertContents(boardVo);
            }
        }
    
        @Test
        @DisplayName("๊ฒ€์ƒ‰")
        @Commit
        public void ๊ฒ€์ƒ‰() throws Exception {
            boardService.findContentsList();
        }
    
        @Test
        @DisplayName("์ˆ˜์ •")
        @Commit
        public void ์ˆ˜์ •() throws Exception {
            List<BoardVo> boardVoList = new ArrayList<>();
            BoardVo boardVo1 = new BoardVo();
            boardVo1.setBoardSeq(1L);
            boardVo1.setTitle("์ฒœ๋‘ฅ์˜ ์‹ ");
            boardVo1.setContents("์ฒœ๋‘ฅ์˜ ์‹  ํ† ๋ฅด");
            boardVo1.setName("thor");
    
            BoardVo boardVo2 = new BoardVo();
            boardVo2.setBoardSeq(2L);
            boardVo2.setTitle("์žฅ๋‚œ์˜ ์‹ ");
            boardVo2.setContents("์žฅ๋‚œ์˜ ์‹  ๋กœํ‚ค");
            boardVo2.setName("loki");
    
            boardVoList.add(boardVo1);
            boardVoList.add(boardVo2);
    
            boardService.updateContentsList(boardVoList);
    
        }
    
    }

    ์ตœ์ข… DB๊ฒฐ๊ณผ

    11๊ฑด ๋ฐ์ดํ„ฐ ๋“ฑ๋ก ํ–ˆ๊ณ  ๊ทธ ์ค‘ 1๋ฒˆ๊ณผ 2๋ฒˆ์˜ ๋ฐ์ดํ„ฐ ์ •์ƒ์ ์œผ๋กœ ์ˆ˜์ •๋จ

    ๊ฐ„๋‹จํžˆ CRU ํ…Œ์ŠคํŠธ ์™„๋ฃŒ ํ–ˆ๊ณ  ์ด์ œ ํ™”๋ฉด๋‹จ ์ž‘์—…

    board_list.html(thymeleaf)

    <!DOCTYPE HTML>
    <html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <!--  bootstrap, jquery cdn load -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css">
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
        <script  src="http://code.jquery.com/jquery-latest.min.js"></script>
        <title>๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก</title>
    </head>
    <body>
    <div class="container">
        <h2>๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก</h2>
        <div>
            <table class="table table-striped">
                <thead>
                <tr>
                    <th>๋ฒˆํ˜ธ</th>
                    <th>์ œ๋ชฉ</th>
                    <th>๋‚ด์šฉ</th>
                    <th>์ž‘์„ฑ์ž</th>
                    <th>์ž‘์„ฑ์ผ</th>
                    <th>์ˆ˜์ •์ผ</th>
                </tr>
                </thead>
                <tbody>
                <tr id="board_tr" th:each="item : ${list}">
                    <td th:text="${item.boardSeq}"></td>
                    <!--  ์ œ๋ชฉ,๋‚ด์šฉ,์ž‘์„ฑ์ž๋Š” ํŽธ์ง‘ ๊ฐ€๋Šฅ ์˜ต์…˜ ๋ถ€์—ฌ-->
                    <td contenteditable="true" th:text="${item.title}"></td>
                    <td contenteditable="true" th:text="${item.contents}"></td>
                    <td contenteditable="true" th:text="${item.name}"></td>
                    <td th:text="${item.regDate}"></td>
                    <td th:text="${item.updateDate}"></td>
                </tr>
                </tbody>
            </table>
            <button type="button" id="updateBtn" class="btn btn-primary">์ˆ˜์ •ํ•˜๊ธฐ</button>
        </div>
    </div> <!-- /.container -->
    
    <script>
        $(document).ready(function () {
            // ์—…๋ฐ์ดํŠธ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ update_contents_list() ํ˜ธ์ถœ
            $("#updateBtn").on("click", function () {
                update_contents_list();
            });
    
            function update_contents_list() {
                // ๊ฐ์ฒด ๋‹ด์„ ๋ฐฐ์—ด
                let tableArr = new Array();
                $("tr#board_tr").each(function (index, item) {
                    let td = $(this).children();
                    // ํ…Œ์ด๋ธ” ๊ฐ์ฒด
                    let td_obj = {
                        boardSeq : td.eq(0).text(),
                        title: td.eq(1).text(),
                        contents : td.eq(2).text(),
                        name : td.eq(3).text()
                    };
                    // ๋ฐฐ์—ด์— ๊ฐ์ฒด๋ฅผ ์ €์žฅ
                    tableArr.push(td_obj);
                });
    
                // ๋น„๋™๊ธฐ๋กœ ์„œ๋ฒ„์— ์—…๋ฐ์ดํŠธ ํ˜ธ์ถœ
                $.ajax({
                    type : "POST",
                    url : "/board/update",
                    data: JSON.stringify(tableArr),
                    dataType: "JSON",
                    contentType: "application/json; charset=UTF-8",
                    // ์„œ๋ฒ„๋กœ ๋ฐฐ์—ด์„ ๋„˜๊ธธ ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ ์•„๋ž˜ ์˜ต์…˜์„ ๋ถ™์ด๋ผ๊ณ  ํ•˜์ง€๋งŒ ๋‚ด ๊ฒฝ์šฐ๋Š” JSONํ™”ํ•œ ์ŠคํŠธ๋ง์œผ๋กœ ๋„˜๊ธฐ๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ž˜๊ฐ€ ์—†์–ด๋„ ์ •์ƒ ์ž‘๋™ํ•œ๋‹ค.
                    // traditional: true,
                    success : function(data){
                        if(data.resultCode === "01")
                            alert("์ˆ˜์ • ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.");
                        location.reload();
                    },
                    error : function(XMLHttpRequest, textStatus, errorThrown){
                        alert("ํ†ต์‹  ์‹คํŒจ.");
                    }
                });
            }
        });
        // End of $(document).ready...
    </script>
    
    </body>
    </html>

    ํ™”๋ฉด์—์„œ ํ•˜๋Š” ์ผ์€ ๊ฐ„๋‹จํ•˜๋‹ค. study_boardํ…Œ์ด๋ธ”์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์„œ ๋ฟŒ๋ฆฌ๊ณ  ์ œ๋ชฉ, ๋‚ด์šฉ, ์ž‘์„ฑ์ž ํŽธ์ง‘์ด ๊ฐ€๋Šฅํ•˜๊ณ  ์ˆ˜์ •ํ•˜๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๋ฒˆํ˜ธ, ์ œ๋ชฉ, ๋‚ด์šฉ, ์ž‘์„ฑ์ž๋ฅผ ๊ฐ์ฒดํƒ€์ž…์œผ๋กœ ๋ฐฐ์—ด์— ๋‹ด์•„์„œ JSON ๋ณ€ํ™˜ ํ›„ ์„œ๋ฒ„๋กœ ๋„˜๊ธด๋‹ค. 

    ํ™”๋ฉด์—์„œ ๋„˜๊ธฐ๋Š” ๋ฐ์ดํ„ฐ ํ˜•ํƒœ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.(๋ฐฐ์—ด์•ˆ์— ๊ฐ์ฒด๊ฐ€ ๋‹ด๊ฒจ ์žˆ๋‹ค.)

    [{"boardSeq":"1","title":"์ฒœ๋‘ฅ์˜ ์‹ ","contents":"๋ง์น˜์˜ ์‹  ํ† ๋ฅด","name":"thor"},{"boardSeq":"2","title":"์žฅ๋‚œ์˜ ์‹ ","contents":"์žฅ๋‚œ์˜ ์‹  ๋กœํ‚ค","name":"loki"},{"boardSeq":"3","title":"์ œ๋ชฉ : 2","contents":"๋‚ด์šฉ : 2","name":"์•„์ด์–ธ๋งจ"},{"boardSeq":"4","title":"์ œ๋ชฉ : 3","contents":"๋‚ด์šฉ : 3","name":"์•„์ด์–ธ๋งจ"},{"boardSeq":"5","title":"์ œ๋ชฉ : 4","contents":"๋‚ด์šฉ : 4","name":"์•„์ด์–ธ๋งจ"},{"boardSeq":"6","title":"์ œ๋ชฉ : 5","contents":"๋‚ด์šฉ : 5","name":"์•„์ด์–ธ๋งจ"},{"boardSeq":"7","title":"์ œ๋ชฉ : 6","contents":"๋‚ด์šฉ : 6","name":"์•„์ด์–ธ๋งจ"},{"boardSeq":"8","title":"์ œ๋ชฉ : 7","contents":"๋‚ด์šฉ : 7","name":"์•„์ด์–ธ๋งจ"},{"boardSeq":"9","title":"์ œ๋ชฉ : 8","contents":"๋‚ด์šฉ : 8","name":"์•„์ด์–ธ๋งจ"},{"boardSeq":"10","title":"์ œ๋ชฉ : 9","contents":"๋‚ด์šฉ : 9","name":"์•„์ด์–ธ๋งจ"},{"boardSeq":"11","title":"์ œ๋ชฉ : 10","contents":"๋‚ด์šฉ : 10","name":"์•„์ด์–ธ๋งจ"}]

    ์„œ๋ฒ„์—์„œ ์ด๋ฅผ @RequestBody๋กœ ๋ฐ›์•„์„œ ์—…๋ฐ์ดํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.

    JSON ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ๋• ๋ฐ˜๋“œ์‹œ ์œ„ ์—๋…ธํ…Œ์ด์…˜์„ ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค. ์•„๋‹ˆ๋ฉด ๊ฐ’์ด null๋กœ ๋“ค์–ด์˜จ๋‹ค.

    controller

    package study.ex1.controller;
    
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.*;
    import study.ex1.service.BoardService;
    import study.ex1.vo.BoardVo;
    
    import java.util.HashMap;
    import java.util.List;
    
    @Controller
    @Slf4j
    @RequiredArgsConstructor
    @RequestMapping(value = "board")
    public class BoardController {
    
        private final BoardService boardService;
    
        @GetMapping(value = "/list")
        public String list(Model model) {
            List<BoardVo> contentsList = boardService.findContentsList();
            model.addAttribute("list", contentsList);
            return "/board/board_list";
        }
    
        @PostMapping(value = "/update")
        @ResponseBody
        public HashMap<String, Object> updateContents(@RequestBody List<BoardVo> boardVoList) {
            HashMap<String, Object> resultMap = new HashMap<>();
            try {
                boardService.updateContentsList(boardVoList);
                resultMap.put("resultCode", "01");
                resultMap.put("result", "success");
            } catch (Exception e) {
                log.info("์—๋Ÿฌ๋‚ฌ์œผ๋‹ˆ ์ž˜ ๋ณด๊ณ  ๊ณ ์ณ~!");
                log.info("exception : {}", e.getMessage());
            }
            return resultMap;
        }
    }

    ์•„๋ž˜๋Š” ํ…Œ์ŠคํŠธ ๋ผ์ด๋ธŒ ๋™์˜์ƒ์ด๋‹ค.(ํ…Œ์ด๋ธ”์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•œ ๋‚ด์šฉ์ด DB์— ์ž˜ ๋ฐ˜์˜์ด ๋œ๋‹ค.)

    ๋ง‰์ƒ ํ•ด๋ณด๊ณ  ๋‚˜๋ฉด ์ •๋ง ๊ฐ„๋‹จํ•˜์ง€๋งŒ ๊ธฐ๋กํ•œ๋‹ค.

    ์ด ์ฝ”๋“œ๋Š” ์ข‹์€ ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๊ณ  ๋‹น์—ฐํžˆ ๋” ์ข‹์€ ๋กœ์ง์ด ์žˆ์„ ๊ฒƒ์ด๋‹ค.

    ๋Œ“๊ธ€