3 minute read


깃허브 repository : SpringBoot class practice


스프링 부트 예제

스프링 부트 프레임 워크로 넘어와서의 게시판 예제입니다.



 @GetMapping("/main")
    public String main(Model model){
        model.addAttribute("list",service.boardList());
        return"board/main";
    }
main mapper 생성


그리고 이에 해당하는 main.html을 board파일 안에 만들어 줍니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
</head>
<body>
  <div class="container">
      <table class = "table table-hover">
          <thead>
            <tr>
                <th>글번호</th>
                <th>작성자</th>
                <th>제 목</th>
                <th>조회수</th>
            </tr>
          </thead>
          <tr th:each="list: ${list}">
            <td>[[${list.boardId}]]</td>
            <td>[[${list.name}]]</td>
              <td>[[${list.title}]]</td>
              <td>[[${list.read}]]</td>
          </tr>
      </table>
  </div>
</body>
</html>
이 예제에서는 부트 스트랩을 이용하기 때문에 부트스트랩 링크를 걸어줬다.


image

실행 화면




제목을 클릭했을 때 상세보기 페이지로 넘어가는 작업을 해줍니다.

  @GetMapping("/view")
    public String view(Model model, int boardId){
        model.addAttribute("view",service.getBoard(boardId));
        return "board/view";
    }
view mapper 생성


그리고 getBoard sql은 만들어 놨으니, 인터페이스와 서비스에 코드를 작성해줍니다.

  Board getBoard(int boardId);
인터페이스(BoardMapper.java)

   public Board getBoard(int boardId) {
        return boardMapper.getBoard(boardId);
    }
BoardService


view.html도 작성해줍니다.

  <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">
    <p>글 번호: [[${view.boardId}]]</p>
    <p>제 목: [[${view.title}]]</p>
    <p>작성자: [[${view.name}]]</p>
    내용: <textarea class="form-control" th:text="${view.content}"></textarea>
    <p>조회수: [[${view.read}]]</p>
</div>
</body>
</html>
view.html


제목을 클릭했을때 view.html로 넘어가야하니 main.html에 a태그를 넣어서 수정해줍니다.

  <td>[[${list.title}]]</td>
기존코드


  <td>
    <a th:href="@{/board/view(boardId=${list.boardId})} ">
          [[${list.title}]]
    </a>
  </td>
수정



image

수정 후main 화면


image

view 화면




이제 게시글 등록기능을 추가해 줍니다. mapper, interface, service에 게시글 등록을 위한 코드를 작성해줍니다.

   <insert id="uploadBoard" parameterType="com.example.springbootpractice.domain.Board">
        insert into tbl_board (title, content, name) values (#{title}, #{content}, #{name});
    </insert>
BoardMapper.xml


    void uploadBoard(Board board);
BoardMapper.java


   public void uploadBoard(Board board){
        boardMapper.uploadBoard(board);
    }
BoardService.java


업로드를 할때 form태그를 post방식으로 제출할 것이기 때문에 업로드 페이지 접속을 위한 get매퍼와 게시글 등록을 위한 post매퍼를 작성해 줍니다.

   @GetMapping("/upload")
    public String upload(Model model){
        return "board/upload";
    }
    @PostMapping("/upload")
    public String uploadBoard(Board board){
        service.uploadBoard(board);
        return "redirect:/board/main";
    }
BoardController.java
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="container">
    <form th:action="@{upload}" method="post">
        이름: <input type="text" class="form-control" name="name">
        제목: <input type="text" class="form-control" name="title">
        내용: <textarea class="form-control" name="content"></textarea>
        <button type="submit">등록</button>
    </form>
</div>
</body>
</html>
upload.html


아직 upload페이지에 접속하는 버튼을 안 만들었으니 직접 링크를 타고 들어가서 게시글이 잘 작성 되는지 테스트 해봅니다.



image

upload 화면


등록 버튼을 누르니 에러가 뜬다.

image

error 발생


Connection이 read-only로 되어있어서 그렇다는 것 같다. read-only를 적용한것은 Service에 Transactional 어노테이션 밖에 없는것 같아서 Transactional(readOnly = false)로 바꿨다.


image

수정


바꿔 줬더니 잘 등록 된다. 근데 다른 사람들은 readOnly = true 였어도 잘 되는데 무슨 문제인지 모르겠다.


image

잘 등록된 모습




남은 update와 delete기능을 구현한다. 위와 동일한 절차로 코드를 작성해준다.


   <update id="updateBoard" parameterType="com.example.springbootpractice.domain.Board">
        update tbl_board set title=#{title}, content=#{content} where boardId = #{boardId};
    </update>

    <delete id="deleteBoard" parameterType="int">
        delete from tbl_board where boardId = #{boardId};
    </delete>
BoardMapper.xml


    void updateBoard(Board board);

    void deleteBoard(int boardId);
BoardMapper.java


    public void updateBoard(Board board){
        boardMapper.updateBoard(board);
    }

    public void deleteBoard(int boardId){
        boardMapper.deleteBoard(boardId);
    }
BoardService.java


   @PutMapping("/update")
    public String updateBoard(Board board){
        service.updateBoard(board);
        return "redirect: /board/main";
    }

    @DeleteMapping("/delete")
    public String deleteBoard(int boardId){
        service.deleteBoard(boardId);
        return "redirect: /board/main";
    }
BoardController.java



새로운 view단 페이지를 만들지 않고 view.html을 수정해서 만들어 줍니다.


<body>
<div class="container">
    <p>글 번호: [[${view.boardId}]]</p>
    <p>제 목: [[${view.title}]]</p>
    <p>작성자: [[${view.name}]]</p>
    <div id="content">
        내용: <textarea class="form-control" th:text="${view.content}" readonly></textarea>
    </div>
    <p>조회수: [[${view.read}]]</p>

    <button id="deleteBtn" class="btn btn-danger btn-sm float-left">삭제</button>
    <button id="updateBtn" class="btn btn-info btn-sm float-right">수정</button>
    <form id="form" th:action="@{/}" method="post">

    </form>
</div>
view.html 수정


추가로 스크립트문을 작성해주고 jquery스크립트를 임포트 해줍니다.

 <script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
    <script src="js/vendor/modernizr-3.8.0.min.js"></script>
    <script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
    <script>window.jQuery || document.write('<script src="@{/js/vendor/jquery-3.4.1.min.js}"><\/script>')</script>
view.html head 태그 안에 삽입


 <script th:inline="javascript">
    $(document).on('ready', function (e) {
        var form = $("#form");
        var boardId = [[${view.boardId}]];
        $(document).on('click', '#deleteBtn', function (e) {
            $('#form').attr("action", "delete");
            form.append("<input type='hidden' name='boardId' value='"+boardId+"'>");
            form.append("<input type='hidden' name='_method' value='delete'>");
            form.submit();
        });
        $(document).on('click', '#updateBtn', function (e) {
            var str = "<input class='form-control' width='250' placeholder='제목 입력' id='updateTitle'>";
            $('#title').html(str);
            str = "<textarea class='form-control' placeholder='내용 입력' id='updateContent'></textarea>";
            $('#content').html(str);
            $('#updateBtn').attr("id", "updateConfirmBtn");
        });

        $(document).on('click', '#updateConfirmBtn', function (e) {
            $('#form').attr("action", "update");
            var updateTitle = $('#updateTitle').val();
            var updateContent = $('#updateContent').val();
            form.append("<input type='hidden' name='boardId' value='"+boardId+"'>");
            form.append("<input type='hidden' name='_method' value='put'>");
            form.append("<input type='hidden' name='title' value='"+updateTitle+"'>");
            form.append("<input type='hidden' name='content' value='"+updateContent+"'>");
            form.submit();
        });
    });
</script>
view.html script

스크립트 문을 작성할 때 큰따옴표와 작은따옴표를 잘 혼용해서 쓰는데 서로 어디서 닫히는지 잘 확인해야겠다. 자동으로 닫히기 때문에 이를 인지를 잘 못해서 오류가 빈번하게 발생한다.



image

view.html


image

view.html. 수정버튼 클릭시 창이 바뀜


image

수정 잘 됨



게시글 예제는 여기까지