조회수 구현 게시글을 클릭해서 포스트를 조회할 때 조회수를 올려주기만 하면 된다.
그러나 이렇게만 한다면 댓글 작성할 때나 같은 아이디로 다시 들어갈 때나 조회수가 계속 올라간다.
이를 방지하기 위해 쿠키를 이용해서 조회수를 구현하는 방법을 기록한다.
쿠키란?
- 서버가 클라이언트에게 보내는 데이터 중 하나로써, 클라이언트는 받은 쿠키 데이터를 로컬영역에 저장한다.
- 다음에 서버를 방문한다면 쿠키를 요청 헤더에 포함해서 서버에게 전달한다.
1. 게시판 DB
CREATE TABLE `tb_board` (
`id` int NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`content` text NOT NULL,
`writer_id` int NOT NULL,
`writer` varchar(20) NOT NULL,
`delete_yn` varchar(1) DEFAULT 'N',
`create_date` datetime DEFAULT NULL,
`views` int DEFAULT '0',
`image` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `writer_id` (`writer_id`),
CONSTRAINT `tb_board_ibfk_1` FOREIGN KEY (`writer_id`) REFERENCES `tb_userinfo` (`id`) ON DELETE CASCADE
)
2. View에 조회수 추가 (게시판 목록 html)
<!-- contents -->
<table class="table caption-top table-bordered table-hover">
<caption>List</caption>
<thead>
<tr>
<th class="text-center" width="50" scope="col">No</th>
<th class="text-center" width="950" scope="col">제목</th>
<th class="text-center" width="180" scope="col">작성자</th>
<th class="text-center" width="200" scope="col">작성일</th>
<th class="text-center" width="150" scope="col">조회수</th>
</tr>
</thead>
<tbody>
<tr th:each="board : ${boardList}">
<td class="mt-5 text-center" scope="row" th:text="${board.id}">1</td>
<td><a th:text="${board.title}" th:href="@{/board/post(id=${board.id})}" style="text-decoration:none; color:black;">제목</a></td>
<td class="text-center" th:text="${board.writer}">작성자</td>
<td class="text-center" th:text="${#dates.format(board.createDate, 'yyyy/MM/dd HH:mm')}">작성일</td>
<td class="text-center" th:text="${board.views}">조회수</td>
</tr>
</tbody>
</table>
- 마지막 줄 th:text="${board.views}" : 조회수
3. Service
// 조회수 증가
public void updateViews(Board board, String username, HttpServletRequest request,
HttpServletResponse response) throws Exception {
Cookie[] cookies = request.getCookies();
Map<String, String> mapCookie = new HashMap<>();
if (request.getCookies() != null) {
for (int i = 0; i < cookies.length; i++) {
mapCookie.put(cookies[i].getName(), cookies[i].getValue());
}
String viewsCookie = mapCookie.get("views");
String newCookie = "|" + board.getId();
// 쿠키가 없을 경우 쿠키 생성 후 조회수 증가
if (viewsCookie == null || !viewsCookie.contains(newCookie)) {
Cookie cookie = new Cookie("views", viewsCookie + newCookie);
response.addCookie(cookie);
boardRepository.updateViews(board);
}
}
}
- request : 쿠키 정보를 얻을 HttpServletRequest 객체
- response : 쿠키 정보를 추가할 HttpServletResponse 객체
- mapCookie.put : HashMap을 이용해 key value로 쿠키 값을 저장
- viewsCookie : hashmap에 views라는 key값으로 저장된 value객체를 저장
- newCookie : 새로운 쿠키를 추가할 때 사용 (id : 게시판 번호)
- 쿠키 객체를 생성하고 추가할 쿠키 값을 초기화
- 2번 게시글 조회 -> (views, null|2)
- 3번 게시글 조회 -> (views, null|2|3) ...
- response.addCookie를 통해 쿠키를 추가하고 조회수 1 증가
- contains -> https://black-mint.tistory.com/39
4. Controller
// 포스트 조회
@GetMapping("/post")
public String readPost(Model model, @RequestParam(required = false) Long id,
Principal principal, HttpServletRequest request,
HttpServletResponse response) throws Exception {
String loginUser = principal.getName();
Board board = boardService.contentLoad(id);
boardService.updateViews(board, loginUser, request, response);
model.addAttribute("board", board);
model.addAttribute("loginUser", loginUser);
return "board/post";
}
- 쿠키를 사용하기 위해 HttpServletRequest request, HttpServletResponse response 를 파라미터로 받는다.