Spring/Tistory

블로그-V3. 조회수 카운팅

JJJAEOoni 2022. 4. 27. 10:56
반응형

 

 

게시글 상세보기 할 때랑, 게시글 목록을 볼 때 둘 다 방문자수를 올려줘야 한다.

 

1. 상세보기 /user/1/post

1번 user의 visit update

 

2. 목록  /post/1

포스트 아이디 1로 findById 해서, 그 오브젝트에 있는 user의 id로 visit update

 

게시글 목록을 볼 때마다 visit을 업데이트 해야하는데 이게 맞나?

아직 save 된 게 없는데 업데이트한다는 게 이상하다.

 

회원 가입할 때 visit을 무조건 INSERT 시켜버리면 된다. 디폴트 데이터로!

회원가입 로직에 추가해주면 되겠다.

 

@Transactional
public void 회원가입(User user) {
    // 1. save 한번
    String rawPassword = user.getPassword(); // 1234
    String encPassword = bCryptPasswordEncoder.encode(rawPassword); // 해쉬 알고리즘
    user.setPassword(encPassword);

    User userEntity = userRepository.save(user);

    // 2. save 두번
    Visit visit = new Visit();
    visit.setTotalCount(0L); // longtime
    visit.setUser(userEntity);
    visitRepository.save(visit);
}

 

 

 


 

 

 

- System.out.println

화면(모니터)에 출력

 

- logger (log4j)

화면(모니터)에 출력

레벨별로 담길 수 있는 로그

 

1. info (정상)

2. debug : 개발환경에서만 로그가 뜨고 배포되고 나면 뜨지 않음

3. error

4. warning (경고) : 프로그램이 돌아가는데 문제는 없지만 나중에 문제가 생길 수 있으니 체크해봐

 

@Slf4j 어노테이션을 달아주면 레벨별 로그를 설정해줄 수 있다.

 

@Transactional
public PostRespDto 게시글목록보기(Integer pageOwnerId, Pageable pageable) {

    Page<Post> postsEntity = postRepository.findByUserId(pageOwnerId, pageable);
    List<Category> categorysEntity = categoryRepository.findByUserId(pageOwnerId);

    List<Integer> pageNumbers = new ArrayList<>();
    for (int i = 0; i < postsEntity.getTotalPages(); i++) {
        pageNumbers.add(i);
    }
    PostRespDto postRespDto = new PostRespDto(
            postsEntity,
            categorysEntity,
            pageOwnerId,
            postsEntity.getNumber() - 1,
            postsEntity.getNumber() + 1,
            pageNumbers);

    // 방문자 카운트 증가
    Optional<User> pageOwnerOp = userRepository.findById(pageOwnerId);
    if(pageOwnerOp.isPresent()) {
        User pageOwnerEntity = pageOwnerOp.get();

        Optional<Visit> visitOp = visitRepository.findById(pageOwnerEntity.getId());
        if(visitOp.isPresent()) {
            Visit visitEntity = visitOp.get();
            visitEntity.setTotalCount(visitEntity.getTotalCount() + 1);
        } else {
            log.error("미친 심각", "회원가입할 때 Visit이 안만들어지는 심각한 오류가 있습니다.");
            // sms 메시지 전송
            // email 전송
            // file 쓰기 : 파일에 로그 남기기
            throw new CustomException("일시적 문제가 발생하였습니다. 관리자에게 문의해주세요.");
        }
    } else {
        throw new CustomException("해당 블로그는 없는 페이지입니다.");
    }
    

    return postRespDto;
}
@Transactional // 더티체킹
public Post 게시글상세보기(Integer id) {
    Optional<Post> postOp = postRepository.findById(id);

    if (postOp.isPresent()) {
        Post postEntity = postOp.get();

        // 방문자 카운트 증가
        Optional<Visit> visitOp = visitRepository.findById(postEntity.getUser().getId());
        if(visitOp.isPresent()) {
            Visit visitEntity = visitOp.get();
            visitEntity.setTotalCount(visitEntity.getTotalCount() + 1);
        } else {
            log.error("미친 심각", "회원가입할 때 Visit이 안만들어지는 심각한 오류가 있습니다.");
            // sms 메시지 전송
            // email 전송
            // file 쓰기 : 파일에 로그 남기기
            throw new CustomException("일시적 문제가 발생하였습니다. 관리자에게 문의해주세요.")
        }

        return postEntity;
    } else {
        throw new CustomException("해당 게시글을 찾을 수 없습니다");
    }
}

 


 

새로고침 하거나, 해당 페이지 접속할 때 (/user/1/post, /post/1)

방문자 수 증가를 한 번만 할 수 있도록 수정해야 한다.

 

request 객체 안에 ip 주소가 있는데 그걸 가지고 오늘 방문한 사람인지 아닌지 확인하려면 테이블이 하나 필요하다.
id       lastConnectedDate       userId(pageOwner)       ipAddress
                    1                4월 28일                             1                             210.10.8.7               
                    2                4월 28일                             2                             210.10.8.7               
                    3                4월 29일                             1                             210.10.8.7               

서버에 접속할 때가 기준이 아닌 해당 페이지 블로그 접속했을 때 확인하여
해당 ip에서 해당 유저 오너 페이지에 해당 날짜에 접속한 기록이 있는지 체크한다.

나만 들어가는 게 아니기 때문에 데이터가 엄청 많이 들어가겠다.

이때 필요한 게 DB 파티셔닝이다. 오늘만 체크할 거니까!!

수평적 분할 -> 전날 데이터를 잘라서 다른 테이블로 옮긴다.
그러면 SELECT 할 때 좋다.
SELECT는 기본적으로 풀스캔이니까!!

 

AND

 

게시글 삭제

 

 

 

 

[출처]

 

https://cafe.naver.com/metacoding

 

메타코딩 : 네이버 카페

코린이들의 궁금증

cafe.naver.com

메타 코딩 유튜브

https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9

 

메타코딩

문의사항 : getinthere@naver.com 인스타그램 : https://www.instagram.com/meta4pm 깃헙 : https://github.com/codingspecialist 유료강좌 : https://www.easyupclass.com

www.youtube.com

 
반응형