게시글 조회수 증가(중복방지를) 구현하려고 한다.
세션과 쿠키 무엇으로 구현을 할지 고민을 했는데, 개인적으로 조회수 증가 중복방지가 크게 중요하다고 생각하지는 않아서, 안전한 세션(도끼로 닭잡는 경우라 생각하여)을 뒤로하고 쿠키로 구현하였다.
특징
@Column(columnDefinition = "integer default 0", nullable = false)
private int view; //조회수
// 게시글 상세조회
@GetMapping(value = "/api/post/{postId}")
public ResponseDto<?> createPost(@PathVariable Long postId,
HttpServletRequest request,
HttpServletResponse response) {
postService.updateView(postId, request, response); // 조회수 증가
return postService.getPost(postId);
}
클라이언트로부터 쿠키를 가져오고 중복방지 쿠키를 응답해줘야 하기때문에 request,resposne를 파라미터로 받는다.
private final static String VIEWCOOKIENAME = "alreadyViewCookie";
@Transactional
public int updateView(Long postId, HttpServletRequest request, HttpServletResponse response) {
Cookie[] cookies = request.getCookies();
boolean checkCookie = false;
int result = 0;
if(cookies != null){
for (Cookie cookie : cookies)
{
// 이미 조회를 한 경우 체크
if (cookie.getName().equals(VIEWCOOKIENAME+postId)) checkCookie = true;
}
if(!checkCookie){
Cookie newCookie = createCookieForForNotOverlap(postId);
response.addCookie(newCookie);
result = postRepository.updateView(postId);
}
} else {
Cookie newCookie = createCookieForForNotOverlap(postId);
response.addCookie(newCookie);
result = postRepository.updateView(postId);
}
return result;
}
/*
* 조회수 중복 방지를 위한 쿠키 생성 메소드
* @param cookie
* @return
* */
private Cookie createCookieForForNotOverlap(Long postId) {
Cookie cookie = new Cookie(VIEWCOOKIENAME+postId, String.valueOf(postId));
cookie.setComment("조회수 중복 증가 방지 쿠키"); // 쿠키 용도 설명 기재
cookie.setMaxAge(getRemainSecondForTommorow()); // 하루를 준다.
cookie.setHttpOnly(true); // 서버에서만 조작 가능
return cookie;
}
// 다음 날 정각까지 남은 시간(초)
private int getRemainSecondForTommorow() {
LocalDateTime now = LocalDateTime.now();
LocalDateTime tommorow = LocalDateTime.now().plusDays(1L).truncatedTo(ChronoUnit.DAYS);
return (int) now.until(tommorow, ChronoUnit.SECONDS);
}
쿠키 이름을 alreadyViewCookie + 게시글번호로 구분한다.
@Modifying
@Query("update Post set view = view + 1 where postId = :postId")
int updateView(@Param(value = "postId") Long postId);
여러번 조회를 했음에도 불구하고 "view" : 1만 나온다.