[Spring MVC] 중복 조회 방지용 쿠키 생성하기

식빵·2021년 12월 19일
1

Spring Lab

목록 보기
1/35
post-thumbnail

☘ 작성 계기

회사에서 게시판 기능을 구현하는 도중에 조회수가 새로고침을 하면 계속해서 오르는 것을 확인했다. 이를 방지하기 위해서 쿠키를 사용한 중복 조회 방지 코드를 짜봤다.


☘ Java 코드


/**
 * 이미 조회한 게시물에 대해서 해당 게시물에 대한 중복 조회수 증가를 방지하는 메소드이다.<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

참고로 위 코드에서 getRemainSecondForTommorow() 메소드에 의해서 쿠키가 상당히 오래 남는다. 쿠키의 유지 시간을 더 짧게 하는 것을 추천한다.



☘ 주의-2

사용자가 개발자 도구를 열어서 해당 쿠키를 지우면 조회수가 중복 증가하게 된다.
이건 쿠키 방식을 사용하면 어쩔 수 없다.
정말 안전하게 하고 싶다면 내 생각에는 Redis 같은 가벼운 DB를 써야지 않을까 싶다.
(혹시 다른 방법이 있다면 댓글 부탁드립니다 😊)

profile
백엔드를 계속 배우고 있는 개발자입니다 😊

1개의 댓글

comment-user-thumbnail
2022년 6월 22일

혹시 response.addCookie(getRemainSecondForTommorow());// 기존에 같은 이름의 쿠키가 있다면 덮어쓴다.
이부분 잘 못 된거 아닐까욤.. response.addCookie(createAccCookie(newCookieVaule))여야할거같아서요..

답글 달기