단기 데이터의 무덤: 일시적 작업 상태와 단기 캐시
파일 변환, 데이터 집계 등 일시적인 작업 진행 상태를 저장하거나 무거운 쿼리 결과를 짧게 캐싱하는 패턴을 익힙니다.
사용자가 거대한 영상 파일을 업로드하고 변환을 요청했다고 가정해 봅시다. 이 작업은 10분이 걸립니다. 사용자는 화면에서 "변환 중 45%..." 같은 진행 상태를 보고 싶어 합니다.
이 진행 상태는 영원히 보관할 데이터가 아니지만, 짧은 시간 동안 아주 빈번하게 업데이트되어야 합니다. 이번 에피소드에서는 일시적인 작업 상태와 무거운 통계 결과를 짧게 보관하는 장소로서의 Redis 활용법을 살펴봅니다.
상태(State)의 수명을 분류하라
서비스를 설계할 때 데이터의 수명을 명확히 분류하는 것은 매우 중요합니다. 영구적인 기록(결제 내역, 회원 정보)은 당연히 메인 데이터베이스로 가야 합니다.
하지만 어떤 데이터는 "지금 당장만 유효하고, 내일이면 아무도 찾지 않는 데이터"입니다. 비디오 인코딩 진행률, 대용량 엑셀 다운로드 준비 상태, 실시간 랭킹 집계 등이 여기에 속합니다.
일시적 작업 상태의 처리 기준
| 상황 | 선택 | 이유 |
|---|---|---|
| 진행률 업데이트 | 0%부터 100%까지 초당 여러 번 변경됨 | 디스크에 쓰지 않고 Redis에만 저장 |
| 최종 완료 결과 | 작업이 끝난 후 다운로드 링크 생성됨 | 메인 DB에 기록하고 Redis의 상태는 삭제 |
| 작업 실패 | 오류 메시지와 재시도 가능 여부 표시 | 단기간 Redis에 에러 상태 보관 후 소멸 |
무거운 쿼리를 막아주는 단기 캐시
진행 상태뿐만 아니라 "자주 바뀌지 않지만 계산하기 엄청나게 무거운 데이터"도 Redis의 훌륭한 타겟입니다.
예를 들어 쇼핑몰 메인 화면의 "지난 24시간 주간 베스트 상품 탑 10"을 생각해 봅시다. 이 데이터를 만들기 위해 수백만 건의 주문 테이블을 읽고 정렬해야 한다면 메인 DB는 비명을 지를 것입니다.
이런 데이터는 1분에 한 번만 계산해서 Redis에 넣어두고(단기 캐시), 모든 사용자는 Redis에서 완성된 데이터를 가져가게 만들면 부하를 획기적으로 줄일 수 있습니다.
무거운 데이터 단기 캐시 패턴
async function getWeeklyBestProducts() {
const CACHE_KEY = 'cache:weekly_best';
// 1. 우선 Redis에 이미 계산된 결과가 있는지 확인합니다.
const cachedData = await redis.get(CACHE_KEY);
if (cachedData) {
return JSON.parse(cachedData); // 있으면 바로 반환! (매우 빠름)
}
// 2. Redis에 없다면, 메인 DB에 엄청 무거운 쿼리를 날려 계산합니다.
const products = await db.query(`SELECT ... FROM ... GROUP BY ...`);
// 3. 계산된 결과를 Redis에 60초(1분) 동안만 저장합니다.
await redis.set(CACHE_KEY, JSON.stringify(products), { EX: 60 });
// 다음 1분 동안 이 함수를 호출하는 수만 명의 사용자는 1번 단계에서 바로 응답을 받습니다.
return products;
}일시적 캐시의 주의점: Cache Stampede (캐시 스탬피드)
단기 캐시 패턴은 훌륭하지만, 주의해야 할 함정이 있습니다. 인기 있는 데이터의 TTL(만료 시간)이 딱 끝나는 그 1초의 순간을 생각해 보세요.
Redis에서 데이터가 지워졌기 때문에, 그 순간 들어온 수천 명의 사용자 요청이 동시에 메인 DB로 무거운 쿼리를 날리게 됩니다. 이 현상을 캐시 스탬피드(Cache Stampede) 현상, 즉 들소 떼가 메인 DB를 짓밟는 현상이라고 부릅니다.
이를 방지하기 위해 데이터를 미리(만료되기 직전에) 백그라운드에서 갱신해 단두거나, 첫 번째 요청만 DB로 보내고 나머지는 잠시 대기시키는 등의 고급 전략을 실무에서는 사용하게 됩니다.
일시적 데이터 관리의 실수
오해 또는 실수
파일 업로드 1% 오를 때마다 DB 업데이트
바로잡기
디스크 I/O가 폭발하므로 Redis 같은 메모리 저장소 활용
오해 또는 실수
모든 데이터를 단기 캐시에 무조건 넣기
바로잡기
사용자별 개인화 데이터는 캐시 적중률이 낮아 오히려 메모리만 낭비됨
개념 퀴즈
퀴즈 답을 맞춰야 학습 완료가 됩니다.무거운 통계 쿼리 결과를 Redis에 단기 캐시했을 때, 캐시가 만료되는 순간 트래픽이 메인 DB로 한꺼번에 몰려 장애를 유발하는 현상을 무엇이라고 하나요?
3줄 요약
- 1진행률 업데이트처럼 짧은 시간 동안 빈번하게 변하는 일시적 상태 관리에 Redis가 적합합니다.
- 2계산이 무거운 통계나 랭킹 결과는 짧은 만료 시간(TTL)을 가진 캐시로 만들어 메인 DB의 부하를 줄일 수 있습니다.
- 3트래픽이 많은 서비스에서는 캐시 만료 순간 메인 DB로 요청이 몰리는 캐시 스탬피드 현상을 대비해야 합니다.