본문으로 바로가기

 

/**
 * 이미 조회한 게시물에 대해서 해당 게시물에 대한 중복 조회수 증가를 방지하는 메소드이다.<br>
 * @param request
 * @param response
 * @param nttId - 게시물 id 값
 */
private void addViewedNttIdToCookie(final HttpServletRequest request, final HttpServletResponse response, final String nttId) {

    Cookie accumulateNttIdCookie = Arrays
        .stream(request.getCookies())
        .filter(cookie -> cookie.getName().equals("alreadyViewNttId"))
        .findFirst()
        .orElseGet(() -> {
            Cookie cookie = createAccNttIdCookie(nttId);    // 조회수 중복 방지용 쿠키 생성
            response.addCookie(cookie);                        // 생성한 쿠키를 response에 담는다.
            bbsService.incrementNttRdCnt(nttId);            // 조회수 증가 쿼리 수행
            return cookie;
        });

    // 한번이라도 조회한 게시물에 대해서는 쿠키값에 해당 게시물의 nttId가 저장된다.
    // 서로 다른 nttId에 대해서는 "/" 로 구분한다.
    // ex) 000000000891/000000000890/000000000889
    String cookieValue = accumulateNttIdCookie.getValue();

    if(cookieValue.contains(nttId) == false) {
        String newCookieValue = cookieValue + "/" + nttId;
        response.addCookie(getRemainSecondForTommorow());    // 기존에 같은 이름의 쿠키가 있다면 덮어쓴다.
        bbsService.incrementNttRdCnt(nttId);                        // 조회수 증가 쿼리 수행
    }

}

/**
 * 조회수 중복 증가(= 새로고침에 의한 조회수 증가)를 방지하기 위한 쿠키를 생성하는 메소드 <br>
 * 일반 게시판(공지사항, 자료실, 질의응답, FAQ, 사용자요청) 전용
 * @param cookieValue
 * @return
 */
private Cookie createAccNttIdCookie(String cookieValue) {
    Cookie cookie = new Cookie("alreadyViewNttId", cookieValue);
    cookie.setComment("조회수 중복 증가 방지 쿠키");    // 쿠키 용도 설명 기재
    cookie.setMaxAge(getRemainSecondForTommorow());             // 하루를 준다.
    cookie.setHttpOnly(true);                // 클라이언트 단에서 javascript로 조작 불가
    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);
}

 

참고1) 이 방식은 AJAX 방식으로 해도 된다. 비동기적으로 Cookie에 값이 채워지는 것이 보일 것이다.

@RequestMapping(value = "/incrementBbsRdCnt.do")
@ResponseBody
public void incrementBbsRdCnt(String id, HttpServletRequest request, HttpServletResponse response) {
    addAlreadyViewedBbsIdToCookie(request, response, id);
}

 

더보기

참고2) 안전하지는 않다...

당연하지만, 사용자가 개발자 도구를 열어서 해당 쿠키를 지우면 조회수가 중복 증가하게 된다.

이건 쿠키 방식을 사용하면 어쩔 수 없다.

가장 궁극적인 안전한 방법은 디비를 사용하는 것이다.