[Spring] 스프링 부트 게시판 만들기-1 게시판 리스트 출력

SpringBoot를 활용하여 간단한 게시판을 만들어야 할 일이 있어 급하게 만든 초간단 게시판을 공유합니다. 총 4개의 포스팅으로 작성할 예정이며 전체 소스는 마지막 게시글에서 GitHub링크를 남겨드리도록 하겠습니다. 최소한의 게시판이 돌아가게끔 기본적인 틀만 정해서 구현하였기에 이 게시판을 기초로 살을 붙여나가며 사용하시면 좋을 듯합니다. SpringBoot와 데이터베이스는 MySql을 사용하였고 SpringBoot에서 데이터 베이스 접근은 마이바티스 라이브러리를 사용해 접근했습니다. 

 

    주요 기능

    1. 게시판 리스트 출력

    2. 게시판 글 등록 (이미지 첨부)

    3. 게시판 상세보기

    4. 댓글과 대댓글 (계층형 댓글)

     

    실행 화면 (게시판 리스트 출력)

    스프링부트 게시판

    테이블 생성

    CREATE TABLE `tb_board` (
    `idx` INT NOT NULL AUTO_INCREMENT,
    `title` VARCHAR(255) NULL,
    `contents` TEXT NULL,
    `image` VARCHAR(255) NULL,
    PRIMARY KEY (`idx`));
    

    게시판 테이블(tb_board)을 만들어줍니다. 간단하게 글 번호(idx), 제목(title), 내용(contents), 이미지(image)만 저장할 수 있게 하였습니다. 데이터베이스는 mysql을 사용하였습니다.

     

     프로젝트 생성 및 환경설정 

    프로젝트 구성

    프로젝트의 전체 구조는 위와 같습니다.

     

    application.properties

    logging.config=classpath:logback-spring.xml
    
    spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
    # harang33
    spring.datasource.url=jdbc:mysql://localhost:3306/데이터베이스명autoReconnect=true&useSSL=false&useUnicode=yes&characterEncoding=UTF-8&autoReconnectForPools=true&serverTimezone=UTC
    spring.datasource.username=아이디
    spring.datasource.password=패스워드
    
    spring.mvc.view.prefix=/WEB-INF/views/
    spring.mvc.view.suffix=.jsp
    
    spring.http.multipart.maxFileSize=10MB
    spring.http.multipart.maxRequestSize=10MB
    

    데이터베이스 연결과 mvc연결을 담당하는 application.properties입니다. datasource안에 자신의 데이터베이스명과 아이디 패스워드를 넣습니다. prefix, suffix의 설정을 통해 모든 View페이지는 views 폴더에 맵핑됩니다. 

     

     

     소스코드  

    게시판 화면 (board.jsp)

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <title>과제</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.22/css/jquery.dataTables.css">
    <script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.js"></script>
      <style>
      .fakeimg {
        height: 200px;
        background: #aaa;
      }
      </style>
    <script type="text/javascript">
    $(document).ready(function() {
        $("#writeBtn").click(function(){
        	location.href ="write";
        })
        $.ajax({url: "boardList", success: function(result){             
            var html = "";
        	result.forEach(function(item){
            	html+= "<tr> <td><a href = 'view?idx=" + item.idx + "'>" + item.title + "</a>"
            })
           $("#listArea").append(html)
           $('#example').DataTable();
         }});
         $("#deleteBtn").click(function(){
        	location.href ="write";
         })
    } );
    
    </script>
    </head>
    <body>
    
    <div class="jumbotron text-center" style="margin-bottom:0">
      <h1>과제</h1>
    </div>
    
    <nav class="navbar navbar-expand-sm bg-dark navbar-dark">
      <div class="collapse navbar-collapse" id="collapsibleNavbar">
        <ul class="navbar-nav">
          <li class="nav-item">
            <a class="nav-link" href="index">홈</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="board">게시판</a>
          </li>
        </ul>
      </div>  
    </nav>
    
    <div class="container" style="margin-top:30px">
    	<div class="row">
    		<div class="col-sm-12">
    	      <h2>게시판</h2>
    			<table id="example" class="display" style="width:100%">
    		        <thead>
    		            <tr>
    		                <th>제목</th>
    		            </tr>
    		        </thead>
    		        <tbody id = "listArea">
    		        </tbody>
    		    </table>
    			<button type="button" class="btn btn-primary" id = "writeBtn">글쓰기</button>
    		</div>
    	</div>
    </div>
    </body>
    </html>
    

    화면은 위와 같이 그렸습니다. 전체적인 디자인은 BootStrap 오픈소스를 사용하였고 실제로 board를 호출하면 html만 나옵니다. tbody 부분은 위의 자바스크립트에서 데이터를 불러와 채워줍니다. ajax를 통해 Controller에 boardList으로 요청을 보내면 컨트롤러에서 매퍼 인터페이스 타고 xml에서 쿼리 실행해 결과적으로는 result에 데이터 값을 가지고 오게 됩니다. 그런 뒤 for문을 돌려  html을 생성해 tbody 부분에 append 시켜주는 방식을 사용하였습니다. 이후 상세보기 페이지를 만들어야 하므로 게시판 글들에 <a> 태그를 줘 상세페이지를 구현하기 위한 사전작업을 해줍니다. 

     

    Controller (IndexController)

    @Controller
    public class IndexController {
    	
        @Autowired
        private BoardService s;
        @RequestMapping(value="/", method=RequestMethod.GET)
        public String root() {
            return "index";
        }
        @RequestMapping(value="/index", method=RequestMethod.GET)
        public String index() {
            return "index";
        }
        @RequestMapping(value="/board", method=RequestMethod.GET)
        public String board() {
            return "board";
        }
    	
        @RequestMapping(value="/boardList", method=RequestMethod.GET)
        @ResponseBody
        public List<Board> boardList(){
            return s.getBoard();
        }
    }
    

    Controller에서는 boardList로 받은 요청을 Service로 넘겨줍니다. (index는 메인화면 board는 게시판 리스트 화면입니다)

     

    Interface (BoardMapper)

    @Repository("BoardMapper")
    public interface BoardMapper {
        public boolean addBoard(Board b);
        public List<Board> getBoard();
        public Board getBoardOne(int idx);
        public boolean addReply(Reply r);
        public List<Reply> getReply(int boardIdx);
    	
    }
    

    먼저 인터페이스를 하나 만들어줍니다. 앞으로 위에 있는 5개의 메서드를 구현할 것입니다.

     

    Service (BoardService)

    @Service
    public class BoardService {
        @Autowired private BoardMapper m;
    	
        public List<Board> getBoard(){
            return m.getBoard();
        }
    }
    

    Service에서는 myBatis getBoard로 실행시킨 데이터를 List에 담아서 컨트롤러로 보내줍니다.

     

    Board DAO

    public class Board {
        private int idx;
        private String title;
        private String contents;
        private String image;
        public Board() {
        // TODO Auto-generated constructor stub
        }
        public int getIdx() {
            return idx;
        }
        public void setIdx(int idx) {
            this.idx = idx;
        }
        public String getTitle() {
            return title;
        }
        public void setTitle(String title) {
            this.title = title;
        }
        public String getContents() {
            return contents;
        }
        public void setContents(String contents) {
            this.contents = contents;
        }
        public String getImage() {
            return image;
        }
        public void setImage(String image) {
            this.image = image;
        }
        public Board(int idx, String title, String contents, String image) {
            super();
            this.idx = idx;
            this.title = title;
            this.contents = contents;
            this.image = image;
        }
    }
    

    게시판 객체도 위와 같이 하나 만들어줍니다.

     

    Mybatis

    <mapper namespace="com.web.mapper.BoardMapper">
        <select id="getBoard" resultType="com.web.domain.Board">
            SELECT
            idx, title, image, contents
            FROM
            tb_board
            ORDER BY idx asc
        </select>
    </mapper>
    

    게시판 리스트를 가지고올 쿼리문입니다. 네임스페이스로 해당 xml 파일과 mapper 인터페이스 파일을 서로 참조합니다. 인터페이스에서 각각 메서드로 xml 파일의 요소들을 맵핑하고 쿼리를 실행합니다.

     

    [Spring] 스프링 부트 게시판 만들기-2 게시판 글 등록 (이미지 첨부)

    [Spring] 스프링 부트 게시판 만들기-3 글 상세보기 페이지 만들기

    [Spring] 스프링 부트 게시판 만들기-4 계층형 댓글 만들기

    댓글

    Designed by JB FACTORY