블로그 별 조회수를 Redis로 확인하기
💡구현 기능
- 아래와 같은 조건의 '내 블로그 글 별 조회수'를 Redis로 확인하는 기능을 만드려고 한다.
1. 블로그 URL의 PATH는 /articles/{id} 형식이다.
2. 로그인 여부와 상관없이 새로고침 될때마다 조회수가 하나 증가한다.
3. 이를 관리하기 위해 적당한 데이터 타입을 선정하고,
4. 사용자가 임의의 페이지에 접속할 때 실행될 명령을 작성해보자.
💡Redis 명령어
- Redis의 String 타입은 숫자 카운터로 사용할 수 있고 값을 증가(INCR) 또는 감소(DECR)시키는 연산을 제공한다.
1) 특정 게시글 조회수 증가
INCR articles:{id}
2) 특정 게시글 조회수 증가 예시
INCR articles:1
INCR articles:2
INCR articles:3
- 1번 게시글 조회수 +1
3) 오늘의 조회수 따로 관리
INCR articles:1:today
- 1번 게시글의 오늘 조회수 +1
4) 하루가 지나면 날짜 키로 변경
RENAME articles:1:today articles:2026-03-05
- 오늘 카운터를 날짜 기준 기록으로 변경
💡Spring 사용 예시
- 조회수 증가 Service
@Service
@RequiredArgsConstructor
public class ArticleViewService {
private final StringRedisTemplate redisTemplate;
public Long increaseView(Long articleId) {
String key = "articles:" + articleId;
return redisTemplate
.opsForValue()
.increment(key);
}
}
- redisTemplate : Spring이 제공하는 API (RedisTemplate)를 통해 Redis 명령을 실행
- opsForValue() : Redis의 String 자료형을 다루는 API
- increment() : 내부적으로 Redis 명령 'INCR key'를 실행
블로그에 로그인 한 사람들의 조회수와 가장 많은 조회수를 기록한 글을 Redis로 확인하기
💡구현 기능
- 아래와 같은 조건의 '블로그에 로그인한 사람들의 조회수와 가장 많은 조회수를 기록한 글'을 Redis로 확인하는 기능을 만드려고 한다.
1. 블로그 URL의 PATH는 `/articles/{id}` 형식이다.
2. 로그인 한 사람들의 계정은 영문으로만 이뤄져 있다.
3. 이를 관리하기 위해 적당한 데이터 타입을 선정하고,
4. 사용자가 임의의 페이지에 접속할 때 실행될 명령을 작성해보자.
5. 만약 상황에 따라 다른 명령이 실행되어야 한다면, 주석으로 추가해보자.
💡Redis 명령어
- 중복을 허용하지 않는 자료형 Set을 활용할 수 있다.
1) Set에 값 추가 (중복 허용 안 됨)
SADD articles:1 alex
SADD articles:1 brad
SADD articles:1 chad
- Redis 내부
articles:1 = {alex, brad, chad}
2) Set에 들어있는 원소 개수 반환
SCARD articles:1
- 결과
3
3) 중복된 값 저장하는 경우 : SADD 반환값은 0
SADD articles:1 alex brad chad
- 이미 내부에 alex, brad, chad 가 저장되어 있다면, 반환값은 0이다.
4) 따라서 SADD의 결과에 따라 명령어 실행 여부 결정 가능
# SADD의 결과에 따라 명령 실행
# 0이면 스킵
# 1이면 Sorted Set에 추가
ZADD articles:ranks 1 articles:1
ZINCRBY articles:ranks 1 articles:1
- ZADD
Sorted Set "articles:ranks"에
member = articles:1
score = 1
로 추가
- ZINCRBY
articles:1의 score를 1 증가
- 가장 높은 조회수의 글을 보고 싶다면
ZRANGE articles:ranks 0 0 REV
💡Spring 사용 예시
import java.util.concurrent.TimeUnit;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ArticleLikeService {
private final StringRedisTemplate redis;
public ArticleLikeService(StringRedisTemplate redis) {
this.redis = redis;
}
/**
* userId가 articleId에 좋아요를 누르면:
* 1) Set에 userId 추가 (중복이면 0)
* 2) 새로 추가된 경우에만 Sorted Set 랭킹 점수 +1
*/
public boolean like(Long articleId, String userId) {
String likeSetKey = "article:" + articleId + ":likes"; // Set
String rankKey = "articles:ranks"; // ZSet
String member = "articles:" + articleId; // ZSet member
Long added = redis.opsForSet().add(likeSetKey, userId); // Redis: SADD
if (added == null) added = 0L;
if (added == 1L) {
redis.opsForZSet().incrementScore(rankKey, member, 1); // Redis: ZINCRBY
return true; // 처음 좋아요 성공
}
return false; // 이미 좋아요 눌렀음
}
public Long likeCount(Long articleId) {
String likeSetKey = "article:" + articleId + ":likes";
return redis.opsForSet().size(likeSetKey); // Redis: SCARD
}
public Double rankScore(Long articleId) {
String rankKey = "articles:ranks";
String member = "articles:" + articleId;
return redis.opsForZSet().score(rankKey, member); // Redis: ZSCORE
}
}
참고 자료
https://teamsparta.notion.site/1-5-1-2242dc3ef51481478520c62135a0e3c9
챕터1-5 : 실습1 | Notion
Redis 설치 및 기본 명령어 사용해보기
teamsparta.notion.site
'심화 > DB' 카테고리의 다른 글
| [DB] Spring에서 Redis 사용해보기 : RedisTemplate 써보기 (0) | 2026.03.03 |
|---|---|
| [DB] Spring에서 Redis 사용해보기 (0) | 2026.03.02 |
| [DB] Redis 타입 살펴보기 (공부중..) (0) | 2026.02.27 |
| [DB] Redis 설치하기 (MacOS) (0) | 2026.02.26 |
| [DB] 인메모리 저장소와 Redis 기초 (0) | 2026.02.25 |