캐싱backendredis
Redis 캐싱 전략 — Cache-Aside만 알아도 충분한 이유
✨ AI 요약
긴 글, 핵심만 먼저 — 이 글을 3줄로 정리해드려요.
조회 15
캐싱 전략 글을 보면 Write-Through, Write-Behind, Read-Through 같은 패턴이 쏟아진다. 결론부터 말하면 웹 서비스의 95%는 Cache-Aside 하나로 충분하다.
Cache-Aside 기본형
async function getPost(id: string) {
const cached = await redis.get(`post:${id}`);
if (cached) return JSON.parse(cached);
const post = await db.post.findUnique({ where: { id } });
if (post) await redis.set(`post:${id}`, JSON.stringify(post), "EX", 300);
return post;
}
읽을 때 캐시를 먼저 보고, 없으면 DB에서 읽어 채운다. 쓸 때는 캐시를 지운다(갱신이 아니라 삭제). 다음 읽기가 자연스럽게 최신 값을 채워 넣는다.
갱신이 아니라 삭제인 이유
쓰기 시점에 캐시를 "갱신"하면 동시 쓰기에서 순서가 꼬였을 때 낡은 값이 캐시에 남는다. 삭제는 최악의 경우가 "캐시 미스 한 번"으로 끝난다. 실패 모드가 훨씬 안전하다.
TTL은 보험이다
무효화 로직이 완벽해도 TTL은 꼭 건다. 버그, 배포 중 유실, 예외 경로 어디선가 삭제가 누락됐을 때 TTL이 최후의 방어선이 된다. 데이터 특성에 따라 1분~1시간 사이에서 정하면 된다.
스탬피드 방지
인기 키가 만료되는 순간 수백 요청이 동시에 DB로 몰리는 게 캐시 스탬피드다. 대응은 두 가지면 충분하다. ① TTL에 지터(무작위 ±10%)를 줘서 동시 만료를 분산 ② 재계산에 락(SET NX)을 걸어 한 요청만 DB에 가게 하기.
Write-Through가 필요해지는 건 쓰기 직후 읽기가 극단적으로 많고 미스 비용이 클 때인데, 그 정도 규모가 되면 그때 도입해도 늦지 않다. 미리 복잡도를 사지 말자.