문제 정의
현재 다음과 같은 방식으로 Redis 키를 구성하여 페이지네이션된 TuningReport 리스트를 캐싱하고 있음
public String pageListKey(String domain) {
return String.format("reports:domain=%s:page=0:size=10:sort=%s:list", domain, TuningReportSortType.LATEST);
}
그러나 사용자의 domain 정보는 MySQL에서 조회해야 하며, 이는 캐시 키 생성 자체가 DB 조회를 필요로 한다는 점에서 Redis 도입의 목적(=DB 부하 감소)을 훼손하고 있음.
👉 DB 부하를 줄이기 위한 캐시인데, 키 생성을 위해 다시 DB를 조회하게 되면 캐시의 의미가 퇴색된다.
즉, "키를 만들기 위해 필요한 정보 자체가 DB에서 온다”
요구사항 요약
- Redis 캐시 조회 이전에 DB 조회가 발생하지 않아야 함
- domain 정보를 기준으로 구성된 캐시 키(reports:domain=...)를 유지하거나 유사한 효과를 유지할 것
- domain 정보는 사용자의 정체성과 밀접하며, 빈번히 변경되지 않음
고려한 해결 방안
1. 사용자의 domain 값을 Redis에 미리 캐싱해두기
- Redis에 user:{userId}:domain 형태로 사용자 domain 값을 1차 캐시로 저장
- 캐시 미스일 경우에만 DB에서 조회하고, Redis에 다시 저장
- 이후 보고서 키 구성 시에는 Redis에서 domain을 조회하여 사용
String domain = redisTemplate.opsForValue().get("user:" + userId + ":domain");
if (domain == null) {
domain = userRepository.findDomainById(userId);
redisTemplate.opsForValue().set("user:" + userId + ":domain", domain, Duration.ofHours(1));
}
String redisKey = pageListKey(domain);
장점
- DB 접근 최소화
- 기존 키 패턴 (domain 기준 키) 유지 가능
- 사용자 속성이 자주 변하지 않는다면 TTL 관리만으로 충분
단점
- 사용자 domain 변경 시 캐시 무효화 혹은 갱신 로직 필요 (방지하기 쉬움)
2. 클라이언트가 API 호출 시 domain 값을 함께 전달
GET /api/reports?domain=cat_lover
장점
- 서버는 키 생성 시 DB/캐시에 접근할 필요 없음
- 성능상 가장 빠름
단점
- 기존에 이미 API 요청 로직이 완성되어 있기 때문에, 이 변경은 프론트엔드 코드 전반에 영향을 미치며 리소스 소모가 큼
3. 캐시 키에 userId를 사용하고 내부에서 domain resolve
String key = String.format("reports:user=%s:list", userId);
- 도메인 기반이 아닌 유저 개인 키를 기준으로 캐싱
장점
- 키 생성 단순
- domain 정보가 필요 없음
단점
- 같은 도메인 사용자 간 캐시 공유 불가 → 캐시 중복 증가 / 메모리 사용량 증가
- 데이터 사용량이 급증하며, 캐시 효율성 저하
최종 선택: 1차 캐시로 사용자 domain 값 Redis에 캐싱
⭐️ 사용자의 domain 정보는 변경이 드물며, 식별자로써 키 생성에 반드시 필요한 속성이다.
따라서 이 정보를 Redis에 먼저 캐싱하고 활용하는 전략은 캐시 설계 원칙을 지키면서도 성능을 최대화할 수 있는 가장 실용적인 접근이다.
후속 처리로 사용자 domain 변경 시 다음 캐시들을 무효화하거나 갱신할 것이 있다.
결론
현재 Redis 키 생성 과정에서 발생한 성능 역행 문제를 해결하기 위해, 1차 캐시로 사용자 domain을 Redis에 저장하고, 이를 통해 캐시 키를 구성하는 전략을 도입함.
이 방식은 DB 부하를 줄이면서 기존 도메인 기반 캐싱 구조를 유지할 수 있으며, 확장성과 성능 면에서 가장 이상적인 선택이다.
끝.
'카카오테크 부트캠프' 카테고리의 다른 글
| 동적인 데이터 캐시 동시성 제어 전략 비교 및 분산 락 선택 (0) | 2025.07.15 |
|---|---|
| Redis 캐시, Cache Stampede 방지 전략 보고서 (TTL Jitter, Mutex Locking) (0) | 2025.07.13 |
| SSE 도입 후 궁금증 완전 해소 – Polling 한계 극복부터 Nginx 설정, Tomcat 병목까지 총정리 (1) | 2025.06.29 |
| MVP 이후의 코드 품질 개선 전략 — 리팩토링 (0) | 2025.06.21 |
| SSE 연결로 인한 HikariCP 커넥션 미반납 문제 (0) | 2025.06.14 |