[5] 글정보 보여주기 및 조회수 구현
들어가며
이전 포스팅에서 게시글을 작성하까지 구현해 봤다 이번 포스팅에서는 게시판의 게시글의 번호를 클릭 시 게시판의 글을 볼 수 있고 클릭시마다 조회수 1식 증가하는 것을 구현해 볼 예정입니다.(조회수 기능은 간단하게 구현)
(GetMapping은 Spring MVC 방식으로 구현했습니다.)
사전 준비
[SpringBoot] 무작정 (REST API)CRUD 게시판을 만들어 보자 게시판 AJAX 글쓰기 구현 및 모든 게시판글 보
[4] 글쓰기 구현하기 및 게시판 글 보여주기 들어가며 이번 포스팅에서는 로그인한 사용자가 있을 때 글쓰기를 작성하여 글을 작성하기능을 구현하고, 작성된 글을 모두 보여주는 것을 구현할
back-stead.tistory.com
Service
BoardServiceImpl
@Override
public Board findByBoardId(Long boardId) {
try {
return boardRepository.findById(boardId)
.orElseThrow(()->new RuntimeException("Board not found with ID: "+ boardId));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Error while finding Board by ID", e);
}
}
public Board countViews(Long boardId){
Board byBoardId = findByBoardId(boardId);
Integer views = byBoardId.getViews();
byBoardId.setViews(++views);
return boardRepository.save(byBoardId);
}
- findByBoardId(...) : 이번에는 예외 처리하는 코드로 작성해봤다.
- countViews(Long boardId) : 드디어 이제 이전에 만들었던 views 컬럼을 사용할 때가 왔다. Id값으로 Board의 views 값을 가져와 1씩 증가시킨다.
저는 조회수를 구현하는 방법은 Spring의 이벤트처리를 활용해서 구현해 봤습니다.
(자세한 내용은 다음에 따로 정리해서 작성하겠습니다.)
ViewEvent
public class ViewsEvent extends ApplicationEvent {
private Board board;
public ViewsEvent(Board board) {
super(board);
this.board = board;
}
public Board getBoard(){
return board;
}
}
생성자는 Board 객체를 받아서 부모 클래스의 생성자를 호출하고, 해당 객체를 내부 변수에 저장하고 getBoard() 메서드를 통해서 내부에 저장된 객체를 반환한다.
Listner
@Service
@RequiredArgsConstructor
public class ClickViewListener implements ApplicationListener<ViewsEvent> {
private final BoardServiceImpl boardService;
@Override
public void onApplicationEvent(ViewsEvent event) {
Board board = event.getBoard();
boardService.countViews(board.getId());
}
}
ClickViewListener는 게시판 조회 시에, 해당 이벤트를 처리하여 게시판의 조회 수를 증가시키는 역할을 수행합니다
Controller
BoardController
...
private final ApplicationEventPublisher eventPublisher;
...
@GetMapping("/board/{boardId}")
public String boardInfo(@PathVariable(name = "boardId") Long boardId,Model model,HttpSession session){
Board byBoardId = boardService.findByBoardId(boardId);
eventPublisher.publishEvent(new ViewsEvent(byBoardId)); //조회시 카운터 증가
getSession(model,session);
model.addAttribute("board",byBoardId);
return "board/boardInfo";
}
게시글 정보를 보는 페이지로 이동했을 때 조회수가 증가하도록 구현했다.
HTML
boardInfo.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/header :: header"></head>
<body>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script th:inline="javascript">
var loginverfiy = false;
$(document).ready(function () {
var login = document.getElementById('loginMember_username').value;
if (login !==null){
loginverfiy = true;
}
})
function opList(){
window.location.href="/board";
}
function updateBoardPage(){
alert("수정버튼 동작");
}
function boardDelete(){
alert("삭제 버튼 동작");
}
</script>
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container-fluid">
<a class="navbar-brand" href="#" th:href="@{/}">CRUD 게시판</a>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav">
<div th:if="${loginMember != null}" class="d-flex justify-content-between">
<div class="nav-item">
<a class="nav-link active" aria-current="page" th:text="'사용자: '+${loginMember.username}">Home</a>
</div>
<div class="nav-item">
<form th:action="@{/logout}" method="post">
<button type="submit" class="btn btn-link">로그아웃</button>
</form>
</div>
</div>
<div th:if="${loginMember==null}" class="d-flex justify-content-between">
<li class="nav-item" >
<a class="nav-link active" aria-current="page" th:href="@{/login}">로그인</a>
</li>
<li class="nav-item">
<a class="nav-link" th:href="@{/createMember}">회원가입</a>
</li>
</div>
</ul>
</div>
</div>
</nav>
<div th:object="${board}">
<div class="container mt-4">
<div class="block table-responsive grid-view">
<table class="table table-bordered">
<hr class="my-4"/>
<colgroup>
<col style="width:15%;">
<col>
<col style="width:15%;">
<col>
</colgroup>
<thead>
<tr>
<th colspan="4">
<div class="col-md-12">
<span id="text_title" th:text="*{title}"></span>
<button type="button" class="btn" onclick="updateBoardPage()">수정</button>
<button type="button" onclick="boardDelete()" class="btn btn-danger">삭제</button>
<button type="button" class="btn btn-info" onclick="opList();">목록</button>
</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<th>등록자명</th>
<td th:text="*{writer}"></td>
<th>등록일</th>
<td th:text="${#temporals.format(board.dateTime, 'yyyy-MM-dd')}">2024-01-20 15:46:22</td>
</tr>
<tr>
<th>조회수</th>
<td colspan="3" th:text="*{views}">5</td>
</tr>
<tr>
<td colspan="4">
<div class="col-md-9 board-contents" th:text="*{content}">
</div>
</td>
</tr>
</tbody>
</table>
<hr class="my-4"/>
</div>
</div>
<input type="hidden" id="input_id" th:value="*{id}">
<input th:if="${loginMember != null}" type="hidden" id="loginMember_username" th:value="${loginMember.username}">
</div>
</body>
</html>
수정 삭제 기능은 아직 구현을 하지 않았으므로 눌렀을 때 동작하는지만 확인하기 위해서 alter로 동작 확인만 해놨습니다.
실행
영상을 보면 0이었지만 게시글의 정보를 볼 때마다 조회수가 1씩 증가하는 것을 확인할 수 있다.(회원이 1회만 증가시키는 것은 구현 x)
다음으로
이번 포스팅에서는 간단하게 조회수를 구현해봤습니다. 다음에는 포스팅 게시글을 수정하는것을 구현해보겠습니다.
감사합니다!!