[Spring] 게시글 조회수 중복 방지
Updated:
I. 개요
게시판에 있어서 조회수는 사용자가 읽고 싶은 글을 선택하는데에 중요한 지표가 된다.
하지만 단순히 게시글에 접근했다고 조회수를 모두 올려준다면, 새로고침만으로도 조회수를 끝없이 올릴 수 있다.
이렇듯 조회수를 임의로 조작하는 것은 커뮤니티에서 흔히 발생할 수 있는 일이므로, 방지해야할 필요가 있다고 생각했다.
II. 쿠키를 통한 구현
/**
조회수 중복 방지
**/
private void viewCountUp(Long id, HttpServletRequest request, HttpServletResponse response) {
    Cookie oldCookie = null;
    Cookie[] cookies = request.getCookies();
    if (cookies != null) {
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals("postView")) {
                oldCookie = cookie;
            }
        }
    }
    if (oldCookie != null) {
        if (!oldCookie.getValue().contains("[" + id.toString() + "]")) {
            postService.viewCountUp(id);
            oldCookie.setValue(oldCookie.getValue() + "_[" + id + "]");
            oldCookie.setPath("/");
            oldCookie.setMaxAge(60 * 60 * 24);
            response.addCookie(oldCookie);
        }
    } else {
        postService.viewCountUp(id);
        Cookie newCookie = new Cookie("postView","[" + id + "]");
        newCookie.setPath("/");
        newCookie.setMaxAge(60 * 60 * 24);
        response.addCookie(newCookie);
    }
}
조회수 중복방지는 필요한 기능이지만, 완벽하게 차단해야 할만큼 중대한 사항은 아니라고 생각했고, 따라서 쿠키를 사용하기로 했다.
아래와 같은 로직으로 흘러간다.
- HttpServletRequest로부터 클라이언트의 쿠키를 가져온다. 먼저 쿠키가- null인지 검사하고, 그렇지 않다면- foreach를 통해 해당 쿠키들 중- postView라는 이름의 쿠키가 있는지 검사한다.
 만약 존재한다면- oldCookie라는 이름으로 가져온다.
- oldCookie가- null이 아니라면, 즉- postView가 존재한다면 해당 쿠키의- value가 현재 접근한 게시글의- id를 포함하고 있는지 검사한다.
 만약 가지고있다면 아무일도 일어나지 않고(조회수가 증가하지 않고), 가지고있지 않다면- postService의- viewCountUp을 통해 해당 게시글의 조회수를 올려주고, 게시글- id를 괄호로 감싸- oldCookie에 추가하고- HttpServletResponse에게 전달한다.
- oldCookie가- null이라면 마찬가지로- postService의- viewCountUp을 통해 게시글의 조회수를 올려주고, 해당 게시글- id를 괄호로 감싼 새로운 쿠키- postView를 생성하여- HttpServletResponse에게 전달한다.
괄호로 id를 감싼 이유
해당 게시글을 이미 조회한적이 있는지 판단하는데에는 contains를 사용했는데, 단순히 숫자만 사용한다면 문제가 생길 수 있다.
예를 들어, 이미 101번 게시글을 조회하여 postView의 값이 101이라고 하자.
이 때, 10번 게시글을 조회하려 한다면, postView쿠키의 101에 포함되어 있는 값이기 때문에 중복된 조회로 여기고 조회수가 증가하지 않을 것이다.
이를 방지하기 위해 숫자를 온전히 검사하고자 [101], [10]과 같은 식으로 포장하여 검사 및 갱신하도록 하였다.
III. 시연

id가 각각 1, 2인 게시글 두개가 있으며, 조회수는 1이고 쿠키는 존재하지 않는 상태이다.

먼저, id가 1인 게시글에 접근했다. oldCookie가 null값이므로 postView쿠키가 생성되고, value로 [1]을 가지게 된다.

기존 조회한 적이 없던 게시글이므로 정상적으로 조회수가 증가한다.

다음으로, id가 2인 게시글에 접근했다. postView를 oldCookie로 가지고, [2]를 포함하지 않으므로 value에 [2]를 추가하여 전달한다.
마찬가지로 조회한 적이 없던 게시글이므로 정상적으로 조회수가 증가했을 것이다.

다시 id가 1인 게시글에 접근했다. postView를 oldCookie로 가지나, [1]을 이미 포함하고 있으므로 쿠키에는 변화가 없다.

1번게시글은 두번 접근했음에도 조회수가 1만 올라간 모습을 볼 수 있다.
Leave a comment