스프링+JPA 조회수 증가(중복방지)

손성우·2022년 8월 15일
0

JPA

목록 보기
3/3
post-thumbnail

게시글 조회수 증가(중복방지를) 구현하려고 한다.
세션과 쿠키 무엇으로 구현을 할지 고민을 했는데, 개인적으로 조회수 증가 중복방지가 크게 중요하다고 생각하지는 않아서, 안전한 세션(도끼로 닭잡는 경우라 생각하여)을 뒤로하고 쿠키로 구현하였다.

특징

  • 사용자가 직접 쿠키에서 중복방지쿠키를 삭제하면 막을 수 없다.
  • 아이디를 변경해도 조회수는 증가하지 않는다.(아이디기준이 아닌 쿠키 기준)
  1. Post
    Post클래스에 아래와 같은 조회수 필드를 추가한다.
@Column(columnDefinition = "integer default 0", nullable = false)
    private int view; //조회수
  1. PostController
// 게시글 상세조회
    @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를 파라미터로 받는다.

  1. PostService

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 + 게시글번호로 구분한다.

  1. PostRepository
    @Modifying
    @Query("update Post set view = view + 1 where postId = :postId")
    int updateView(@Param(value = "postId") Long postId);
  1. 결과

여러번 조회를 했음에도 불구하고 "view" : 1만 나온다.

profile
백엔드 개발자를 꿈꾸며 공부한 내용을 기록하고 있습니다.

0개의 댓글