개요
- Redis를 사용해서 사용자가 게시글을 조회할 때마다 redis를 통해 조회 여부를 확인하고, 처음 조회하는 경우만 조회수가 올라가는 기능을 생성하였다
- 게시판 관련 기능/화면을 설계하면서 다른 팀원에게 받았던 피드백 중에 조회수 관련 기능이 있었다! 로그인 시 사용하고 있는 redis를 사용하면 구현할 수 있을 것 같아 적용해 보았다
관련 개념 정리
Redis
- key-value 저장소로, 다양한 형태의 데이터를 메모리에 저장하여 빠른 데이터 처리를 가능하게 한다
- 조회수 기능 구현 시에는 set 데이터형을 사용하여 (중복 허용 X) 같은 사용자가 게시글을 다시 조회해도 중복 등록되지 않도록 처리하였다
SpringRedisTemplate
- SpringBoot는 Redis와의 통합을 위한 여러 편의 기능을 제공한다. Spring에서 Redis를 편하게 사용할 수 있게 해주는 class 중 하나로, 문자열 처리에 최적화되어 있다.
@Modifying
- @Query와 함께 사용되어, 쿼리가 데이터를 변경하는 작업 (insert, update, delete)임을 나타낸다
- @Transactional과 함께 데이터의 일관성을 유지하고 안정성을 보장
설정
redis:
image: redis:latest
restart: always
command: redis-server --port {port}
container_name: study_redis
labels:
- "name=redis"
- "mode=standalone"
ports:
- {port}:{port}
volumes:
- REDISDATA:/data
코드
- 조회수 update 쿼리 생성 (repository)
@Modifying
@Transactional
@Query("UPDATE Post p SET p.viewCnt = p.viewCnt + 1 WHERE p.postId = :postId")
void incrementViewCount(@Param("postId") Long postId);
- 조회수 update 비지니스 로직 생성(service)
- redis에 게시글 ID와 로그인한 member의 id로 구성된 key가 존재하지 않으면 해당 게시글의 조회수 상승, 아니라면 아무 일도 일어나지 않음
- 해당 로직을 게시글 상세 조회시에 연동하였다
private final StringRedisTemplate redisTemplate;
...
public void incrementViewCntIfNotViewed(Post post) {
Long loginMemberId = getLoginMember().getMemberId();
String key = "post:viewCount:" + post.getPostId() + ":" + loginMemberId;
Boolean alreadyViewed = redisTemplate.opsForSet().isMember(key, String.valueOf(loginMemberId));
if (Boolean.FALSE.equals(alreadyViewed)) {
redisTemplate.opsForSet().add(key, String.valueOf(loginMemberId));
postRepository.incrementViewCount(post.getPostId());
}
}
구현 확인
-
- 조회되지 않은 게시글 목록

-
- 관리자의 계정으로 1번째, 3번째 row의 게시글 조회

- redis에 게시글 id와 관리자의 id로 key가 등록된다

- 관리자가 다시 첫 번째 row의 게시글을 조회해도 조회수는 증가하지 않는다
- 지나의 계정으로 첫번째, 2번째, 4번째 row의 게시글 조회

- redis에 게시글 id와 지나의 id로 key가 등록된다

느낀 점
- 조회수 같은 경우 db 커넥션이 지나치게 많아질 것 같아 어떻게 처리해야 하나 하는 고민이 있었는데, redis를 사용함으로써 불필요한 DB 접근을 줄여 DB에 가해지는 부하를 줄일 수 있었다
- 조회수처럼 자주 변경되지만 데이터의 정확성이 실시간성을 요구하지는 않는 정보를 관리할 때는 시스템 성능을 생각해서 redis를 도입하는 것을 고려해봐야겠다!!
Redis로 조회수 기능을 구현하셨군요!