4단계
Redis 의 역할 5가지
25 분
Redis 의 역할 5가지
"Redis 가 뭐야?" 에 답이 여러 개 있는 건 이유가 있어요. 용도가 5 가지.
1. 캐시 (cache)
가장 흔한 사용. DB 결과를 TTL 두고 저장.
async function getUser(id: number) {
const cached = await redis.get(`user:${id}`);
if (cached) return JSON.parse(cached);
const user = await db.query("SELECT * FROM users WHERE id=$1", [id]);
await redis.setex(`user:${id}`, 300, JSON.stringify(user)); // 5분
return user;
}
- TTL 필수 (무한 저장 금지)
- invalidation 은 별도 (mutation 후 DEL)
2. 세션 (session)
JWT 대신 서버 세션을 Redis 에.
const sid = crypto.randomUUID();
await redis.setex(`sess:${sid}`, 3600, JSON.stringify({ userId, role }));
res.cookies.set("session", sid, { httpOnly: true, maxAge: 3600 });
장점: 즉시 무효화 (DEL). 단점: 모든 요청이 Redis 히트.
3. Rate limit
const bucket = Math.floor(Date.now() / 60000);
const k = `rl:${ip}:${bucket}`;
const count = await redis.incr(k);
if (count === 1) await redis.expire(k, 120);
if (count > 60) return 429;
sliding window · token bucket 등 변형 다수.
4. Pub/Sub
// publisher
redis.publish("notifications", JSON.stringify({ userId, message }));
// subscriber
const sub = redis.duplicate();
await sub.subscribe("notifications");
sub.on("message", (_, raw) => {
const { userId, message } = JSON.parse(raw);
// 웹소켓 브로드캐스트
});
한 프로세스만 연결된 웹소켓 서버가 여러 앱 인스턴스로 이벤트 뿌릴 때.
5. 분산 락
async function withLock(key: string, ttl: number, fn: () => Promise<void>) {
const acquired = await redis.set(`lock:${key}`, "1", "EX", ttl, "NX");
if (!acquired) throw new Error("locked");
try { await fn(); }
finally { await redis.del(`lock:${key}`); }
}
// 예: cron 이 2 인스턴스에서 동시 실행 막기
await withLock("daily-report", 600, generateReport);
Redlock 알고리즘은 복수 Redis 필요. 단일 Redis 로도 "같은 cron 중복 방지" 같은 가벼운 락은 충분.
6. 역할별 분리 (선택)
트래픽 · 장애 영향 범위 분리 목적으로 Redis 인스턴스 여러 개를 둘 수도:
redis-cache— 사라져도 DB 재호출로 복원redis-session— 사라지면 사용자 재로그인 필요redis-queue— 작업 큐
MVP 는 하나로 충분.
7. 어떤 자료구조?
| 자료구조 | 용도 |
|---|---|
| String | 캐시 · 카운터 |
| Hash | 필드 많은 객체 (부분 업데이트 효율) |
| List | 큐 · 최근 N 개 |
| Set | 유일한 값 모음 (좋아요 · follow) |
| Sorted Set | 랭킹 · 시간순 feed |
| Stream | 로그 · 이벤트 스트림 (Kafka 경량 대체) |
8. 메모리 한계
Redis 는 메모리 기반. 과적재 시 OOM.
maxmemory 2gb
maxmemory-policy allkeys-lru
allkeys-lru — 메모리 꽉 차면 오래 안 쓴 키 제거. 캐시 용도 기본.
9. 자주 걸리는 자리
- TTL 없이 — 메모리 폭증
- 큰 값 (MB 단위) — 네트워크 · 메모리 낭비. 큰 건 S3 + URL 캐싱
- 연결 풀 없이 — 매 요청 connect = 느림. ioredis 자동 풀
- Pub/Sub 로 persistent 큐 — 메시지 놓침. 영구 큐는 BullMQ · Kafka
10. 언제 Redis 필요 없나?
- 트래픽 작고 DB 쿼리 충분히 빠름
- 단일 서버 (락 · pub/sub 불필요)
- Next.js
unstable_cache로 ISR 대체 가능
추가 의존성을 늘리는 것은 실제 병목이 생긴 뒤에.
하고픈 말
Redis 를 "그냥 빠른 DB" 로 쓰면 메모리 낭비. 5 가지 역할을 구분하고 각각에 맞는 자료구조를 고르는 게 진짜 가치.
Next
- 05-three-layer-cache