들어가기 전에
하기 포스팅은 "스프링부트 시작하기(김인우 저)" 책을 공부하며 적은 포스팅입니다. 이번 시간에는 앞서 등록한 게시글을 확인할 수 있는 상세 화면을 만들어 보겠습니다.
게시글 상세 화면 만들기
게시글 상세 화면 만들기 전 조회 로직의 흐름에 대해 먼저 살펴보겠습니다.
- 목록 화면에서 상세 내용을 확인하고 싶은 글을 선택합니다. 즉, 목록 화면에서 선택된 글의 상세 화면을 호출하는 기능이 필요합니다.
- 선택된 글의 상세 내용을 조회하고 조회수를 증가시킵니다. 즉, 상세 내용을 조회할 때 비즈니스 로직은 목록 조회와 다르게 두 가지가 됩니다. 비즈니스 로직을 처리하는 서비스 영역에 두 가지 작업(게시글 조회 & 조회수 증가)을 진행해야 합니다.
- 조회된 글 내용을 화면에 표시합니다.
목록 화면 수정하기
먼저 게시글을 선택하고, 선택된 게시글의 상세내용을 조회하는 주소를 호출할 수 있도록 게시글 목록 화면을 수정해야 합니다.
boardList.html 파일의 <table> 내 목록을 보여주는 부분을 아래와 같이 수정합니다.
// boardList.html
// [ AS - IS ]
<td class="title" th:text="${list.title}"></td>
// [ TO - BE ]
<td class="title">
<a href="/board/openBoardDetail.do?boardIdx="
th:attrappend="href=${list.boardIdx}"
th:text="${list.title}"></a></td>
- <a href="/board/openBoardDetail.do?board_idx=" th:attrappend="href=${list.board_idx}" th:text="${list.title}"></a>: <a> 태그를 이용해서 게시글 상세 화면으로 링크를 연결합니다. 상세 화면의 주소를 호출할 때에는 선택된 게시글 번호를 파라미터로 추가합니다.
컨트롤러 영역
BoardController 클래스에 글 상세 내용을 조회하는 로직을 추가합니다.
...
import org.springframework.web.bind.annotation.RequestParam;
...
...
@RequestMapping("/board/openBoardDetail.do")
public ModelAndView openBoardDetail(@RequestParam int boardIdx) throws Exception {
ModelAndView mv = new ModelAndView("/board/boardDetail");
BoardDto board = boardService.selectBoardDetail(boardIdx);
mv.addObject("board", board);
return mv;
}
...
서비스 및 매퍼 영역
서비스 영역에서는 글 조회 및 조회수 증가 두 가지 로직이 필요합니다. 따라서, 서비스 영역에서는 두 가지 로직을 처리하게 됩니다.
// BoardService.java
...
BoardDto selectBoardDetail(int boardIdx) throws Exception;
...
// BoardServiceImpl.java
...
@Override
public BoardDto selectBoardDetail(int boardIdx) throws Exception {
boardMapper.updateHitCount(boardIdx);
BoardDto board = boardMapper.selectBoardDetail(boardIdx);
return board;
}
...
- boardMapper.updateHitCount(boardIdx): 선택된 게시글의 조회수를 증가시킵니다.
- BoardDto board = boardMapper.selectBoardDetail(boardIdx): 선택된 게시글의 내용을 조회합니다.
BoardServiceImpl 클래스를 보면, 두 가지 로직을 처리하기 위해 매퍼를 각각 호출하는 것을 볼 수 있습니다.
해당 서비스 로직 관련 매퍼 코드는 아래와 같이 추가하면 됩니다.
// BoardMapper.java
...
void updateHitCount(int boardIdx) throws Exception;
BoardDto selectBoardDetail(int boardIdx) throws Exception;
...
SQL 작성하기
sql-board.xml에 조회수 증가와 게시글 상세 내용을 조회하는 쿼리를 작성하도록 하겠습니다. 하기 쿼리문 역시 기존에 만든 <mapper> 태그 내에 넣어야 합니다.
...
<update id="updateHitCount" parameterType="int">
<![CDATA[
UPDATE
t_board
SET
hit_cnt = hit_cnt + 1
WHERE
board_idx = #{boardIdx}
]]>
</update>
<select id="selectBoardDetail" parameterType="int" resultType="board.board.dto.BoardDto">
<![CDATA[
SELECT
board_idx, title, contents, hit_cnt,
created_datetime,
creator_id
FROM
t_board
WHERE
board_idx = ${boardIdx} AND deleted_yn = 'N'
]]>
</select>
...
뷰 작성하기
마지막으로 게시글 상세 내용을 사용자에게 보여주기 위한 화면을 만들어야 합니다. boardDetail.html 파일을 templates/board 내에 생성하여 하기 내용을 넣어줍니다.
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>board</title>
<link rel="stylesheet" th:href="@{/css/style.css}"/>
</head>
<body>
<div class="container">
<h2>게시글 상세 화면</h2>
<table class="board_detail">
<colgroup>
<col width="15%"/>
<col width="35%"/>
<col width="15%"/>
<col width="35%"/>
</colgroup>
<caption>게시글 상세내용</caption>
<tbody>
<tr>
<th scope="row">글 번호</th>
<td th:text="${board.boardIdx}"></td>
<th scope="row">조회수</th>
<td th:text="${board.hitCnt}"></td>
</tr>
<tr>
<th scope="row">작성자</th>
<td th:text="${board.creatorId}"></td>
<th scope="row">작성일</th>
<td th:text="${#temporals.format(board.createdDatetime, 'yyyy-MM-dd HH:mm:ss')}"></td>
</tr>
<tr>
<th scope="row">제목</th>
<td colspan="3">
<input type="text" id="title" name="title"
th:value="${board.title }"/>
</td>
</tr>
<tr>
<td colspan="4" class="view_text">
<textarea title="내용" id="contents" name="contents"
th:text="${board.contents }"></textarea>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
- 게시글 상세 화면을 호출하면, 게시글의 상세 내용을 조회하고 그 결과를 board라는 키로 뷰에 넘겨주었습니다. 이를 통해 전달받은 데이터 중 사용자가 변경하면 안되는 정보(조회용 정보 - 글 번호, 조회수, 작성자, 작성일)는 화면에 보여주기만 합니다(input 태그 없음).
- 사용자가 변경할 수 있는 제목 및 내용은 <input> 태그와 <textarea>를 이용하여 수정할 수 있도록 합니다.
- 수정 및 삭제 기능을 추후 구성하기 위해 게시글 상세화면에서 수정 및 삭제를 할 수 있도록 버튼을 미리 생성해두었습니다.
수정 및 삭제는 로그인 여부나 게시글 비밀번호를 이용하여 처리하게 할 수도 있겠지만, 여기서는 기본 기능을 먼저 알아보기 위해 추가 기능을 고려하지 않고 기본 기능만 체크해 본다고 생각하면 됩니다.
실행 결과 확인하기
실행 결과를 확인했을 때, localhost:8080/board/openBoardList.do까지는 문제가 없었지만, 막상 게시글을 클릭하면 하기와 같은 에러가 발생했다.
해당 에러는 컨트롤러에서 뷰를 연결하는 과정에서, 아래와 같이 /board/openBoardDetail이라고.. 경로를 잘못 지정해서였다. 혹시, 위 에러가 발생한다면, 필자와 동일한 문제는 아닌지 살펴보길 바란다😅
@RequestMapping("/board/openBoardDetail.do")
public ModelAndView openBoardDetail(@RequestParam int boardIdx) throws Exception {
ModelAndView mv = new ModelAndView("/board/openBoardDetail");
BoardDto board = boardService.selectBoardDetail(boardIdx);
mv.addObject("board", board);
return mv;
}
위 에러를 수정하고 난 뒤, 아래와 같이 게시글 상세 페이지가 호출됨을 확인할 수 있었다.
- 게시글 목록에서 게시글을 클릭하기 전 조회수와, 게시글 상세 화면에서의 조회수에 차이가 있는 것을 확인할 수 있습니다. 제대로 + 1이 되었음을 알 수 있습니다.
- 게시글 상세 화면에서는 제목과 내용은 수정할 수 있도록 <input>, <textarea> 태그로 들어가있음을 확인할 수 있습니다.
'FRAMEWORK > Spring' 카테고리의 다른 글
[SpringBoot] 게시판 구현하기 7 (스프링의 다양한 기능 살펴보기 - 로그) (1) | 2020.12.25 |
---|---|
[SpringBoot] 게시판 구현하기 6 (게시글 수정 및 삭제 기능 만들기) (1) | 2020.12.22 |
[SpringBoot] 게시판 구현하기 4 (게시글 등록 기능 생성하기) (0) | 2020.12.21 |
[SpringBoot] 게시판 구현하기 3 (게시판 목록 만들기) (2) | 2020.12.21 |
[SpringBoot] 게시판 구현하기 2 (게시판을 만들기 위한 기본 설정) (1) | 2020.12.13 |