[게시판 만들기] IntelliJ를 활용한 게시판 만들기 3탄

Jinju Bae·2022년 2월 20일
0

더미 데이터 삽입하기

이전 포스팅에서 h2 console 실행창에 sql 문을 입력해 테이블을 만들었다.

여기에 여러 값을 삽입해보자.

CREATE TABLE tbl_board(
boardId Long auto_increment,
title varchar (30) not null,
content varchar (30) not null,
name varchar (30) not null,
read number (30) not null default 0,
primary key(boardId)
);
INSERT INTO tbl_board( title, content, name, read) VALUES ('제목1', '내용1', '이름1', 0);
INSERT INTO tbl_board( title, content, name, read) VALUES ('제목2', '내용2', '이름2', 0);
INSERT INTO tbl_board( title, content, name, read) VALUES ('제목3', '내용3', '이름3', 0);
INSERT INTO tbl_board( title, content, name, read) VALUES ('제목4', '내용4', '이름4', 0);
INSERT INTO tbl_board( title, content, name, read) VALUES ('제목5', '내용5', '이름5', 0);
INSERT INTO tbl_board( title, content, name, read) VALUES ('제목6', '내용6', '이름6', 0);
INSERT INTO tbl_board( title, content, name, read) VALUES ('제목7', '내용7', '이름7', 0);
INSERT INTO tbl_board( title, content, name, read) VALUES ('제목8', '내용8', '이름8', 0);
INSERT INTO tbl_board( title, content, name, read) VALUES ('제목9', '내용9', '이름9', 0);
INSERT INTO tbl_board( title, content, name, read) VALUES ('제목10', '내용10', '이름10', 0);

insert 한 줄만 작성할 때는 문장 끝에 세미콜론 (;) 을 찍지 않아도 상관없다.

하지만 여러 실행문을 입력할 때는, 그 문이 끝난다는 표시를 하기 위해 꼭 매 실행문마다 세미콜론을 찍어줘야 한다.

select 구문 (select * from tbl_board) 을 통해 삽입된 값을 확인해보자.

잘 삽입된 것을 확인할 수 있다.

컨트롤러 수정

아래 코드에서 주석에 '추가'라고 되어 있는 부분을 추가해준다.

package wedatalab.bulletinboard.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import wedatalab.bulletinboard.service.BoardService;

@Controller

@RequestMapping("/board/**")
@RequiredArgsConstructor
public class BoardController {

    private final BoardService service;

    @GetMapping("/hello")
    public String Hello() {
        return "/boards/hello";
    }

    @GetMapping("/test")
    public String test(Model model) {
        model.addAttribute("cnt", service.boardCount());
        model.addAttribute("test", service.boardList());

        return "/boards/hello";
    }
    
    // 추가
    @GetMapping("/main")
    public String main(Model model) {
        model.addAttribute("list", service.boardList());
        
        return "/boards/main";
    }
}

추가한 코드는 다음의 과정을 거쳐 실행된다. IntelliJ 에서 ctrl 을 누른 채 아래 하이라이트 된 메소드를 클릭하며 과정을 따라가보자.

  • 주소창에 http://localhost:8080/board/main 를 입력하면 main() 을 실행한다.

  • main( ) 은 service 의 boardList( ) 를 실행한다.

  • BoardMapper 인터페이스의 getList( ) 를 실행한다.

  • BoardMapper.xml 의 getList( ) 과정을 수행해 "list" 에 게시글 정보들을 삽입한다.

return 값은 templates>boards 에 있는 main 이라는 파일을 보여준다는 의미다.

그런데 지금 boards 폴더에 hello.html 밖에 없다.

main.html 을 만들어서 사용자에게 보여주는 페이지를 작성해보자.

main.html 생성

  • resources>templates>boards 폴더에 main.html 을 생성한다. (new - HTML file)

  • 아래의 코드를 주석을 제외하고 입력한다.

<!DOCTYPE html>
<html xmlns xmlns:th="http://www.w3.org/1999/xhtml" : th="http://www.thymeleaf.org">
<head>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="container">
    <table class="table table-hover">
        <thead>
        <th>글번호</th>
        <th>작성자</th>
        <th>제목</th>
        <th>조회수</th>
        </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>

태그들의 class 부분은 부트스트랩 사용으로, 공식 홈페이지에 방문하면 사용법 등 다양한 정보를 얻을 수 있다.

www.w3schools.com/bootstrap4/

페이지에 들어간 후 왼쪽의 카테고리에서 원하시는 태그를 찾아 입력해주면 된다.

타임리프 문법은 th:text, th:each등과 같은 형태로 사용하는데, 이도 공식 홈페이지에서 다양한 설명을 참조할 수 있다.

www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#standard-expression-syntax

<table class="table table-hover">
	<thead>
    	<th>글번호</th>
        <th>작성자</th>
        <th>제목</th>
        <th>조회수</th>
    </thead>
    <tr th:each="list :${list}"> 
        <td>[[${list.boardId}]]</td>
        <td>[[${list.name}]]</td>
        <td>[[${list.title}]]</td>
        <td>[[${list.read}]]</td>
    </tr>
</table>
을 자세히 살펴보자.
  • th:each 는 반복문의 동작을 수행한다. th:each="사용 이름 : ${model 의 이름}" 형식으로 사용할 수 있다.

  • 컨트롤러에서 "list" 라는 model 객체에 게시글 정보를 넣었기 때문에 th:each="변수 이름 : ${list}" 의 형식으로 사용할 수 있다.

  • "list" model 객체에는 총 10개의 데이터가 있기 때문에 th 문이 10번 반복된다.

  • 그리고 하위 td태그로 데이터베이스에 삽입했던 값들을 화면에 보여줄 테이블에 삽입한다.

  • [[${~}]] 는 타임리프 문법으로, 값을 출력해준다.

초기에 h2 database 에 삽입했던 데이터 10개가 모두 정상적으로 출력되는 것을 확인할 수 있다.

게시글 내용 보기

지금까지 게시글 작성자, 제목 등 기본 정보를 띄워봤다.

하지만 게시글 제목만으로는 정보가 부족하다. 우리에겐 제목뿐 아니라 내용도 필요하다.

게시물의 내용을 볼 수 있도록 해보자.

BoardMapper.xml 수정

다음의 코드를 BoardMapper.xml 에 추가한다.

<select id="getBoard" parameterType="Long" resultType="wedatalab.bulletinboard.domain.Board">
    SELECT
    *
    FROM tbl_board where boardId=#{boardId};
</select>
  • id 는 getBoard 이며, 매개변수 타입은 Long 이다.

  • 매개변수에 해당되는 boardId 를 가진 Board 의 데이터를 반환한다.

BoardMapper.interface 수정

BoardMapper.interface 에 아래의 코드를 추가해준다.

Board getBoard(Long boardId);
  • Long 타입 매개변수 boardId 를 boardMapper.xml 의 getBoard 로 넘겨준다.

BoardService.class 수정

BoardService.class 에 아래의 코드를 추가해준다.

  public Board getBoard(Long boardId) {
      return boardMapper.getBoard(boardId);
  }
  • getBoard 메소드는 컨트롤러로 primary key 가 매개변수 boardId 인 게시글의 내용을 반환한다.

BoardController.class 수정

마지막으로 BoardController.class 에 아래의 코드를 추가해준다.

    @GetMapping("/view")
    public String viewBoard(Model model, Long boardId) {
        model.addAttribute("halo", service.getBoard(boardId));

        return "/boards/view";
    }

이로써 http://localhost:8080/board/view 에 접근했을 때 "halo" 라는 model 객체에 위에서 작성했던 쿼리문의 결과값을 저장한다.

(내가 참고한 블로그에서는 model 객체 이름을 "view"라고 했는데 그럼 view.html 파일 자체와 구별하여 이해하기가 힘들어서 "halo" 라고 바꾸었다. "halo" model 객체는 view 파일에 전송하는 데이터를 말하기 때문에 view.html 파일 자체와 다르다.)

return "/boards/view"; 란

"halo" 라는 변수를 가지고 있는 (예를 들어, [[${halo.title}]] 가 이에 해당한다.) boards/view 페이지를 반환해 사용자가 볼 수 있게 동작한다.

그런데 해당 디렉토리에 view 라는 이름을 가진 파일이 없으니 만들어주겠다.

view.html 생성

  • resources>templates>boards 폴더에 view.html 파일을 생성한다. (마우스 우클릭 - new - HTML file)

  • view.html 파일에 아래의 코드를 입력한다.

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

위의 view.html 파일은 "halo" 라는 변수를 가지고 있다. 따라서 컨트롤러에서 만든 "halo" 라는 model 객체에 담긴 데이터를 받을 수 있다.

완성이 되었으니 이제 스프링부트를 구동하고 아래의 url 을 주소 창에 입력해 이동한다. url 에 게시물 번호를 넣어줘야 하기에 「 http://localhost:8080/board/view?파라미터이름=값 」 의 형태로 접근해보자.

http://localhost:8080/board/view?boardId=1

위와 같이 1번 게시물의 내용을 볼 수 있다.

그리고 다음의 url 을 입력해보자.

http://localhost:8080/board/view?boardId=2


2번 게시물의 내용도 볼 수 있다.

그러나 게시판의 글을 볼 때마다 주소를 일일이 입력하는 것은 번거롭다.

대신 게시판 리스트에서 제목을 클릭하면 상세내용을 볼 수 있게 만들고 싶다.

이를 위해 main.html 을 수정해보자.

제목을 클릭하여 게시글 상세보기

간단한 타임리프 링크 문법을 사용해 main.html 을 수정해보자.

원래 아래와 같은 코드를

            <td>[[${list.title}]]</td>

다음과 같이 수정하면 된다.

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

href 는 링크 이동이 가능하게 하는 속성이다.

즉, 게시글 제목을 클릭하면 「 http://localhost:8080/board/view?boardId=누른게시글번호 」 로 이동하게 된다.

먼저 localhost:8080/board/main 으로 이동하면

게시글 리스트가 나타나고,

각 게시글 제목을 클릭하면

게시글 내용을 볼 수 있다.

3편까지 오느라 수고 많았다~!

다음 편에는 게시글을 작성하는 방법에 대해 알아볼 것이다.

profile
진주개발일지 (珍珠開發日誌)

0개의 댓글