Redis 활용 사례: 캐싱, 큐, 속도 제한

Backend2026-10-06TryQuickToolBox

사용자가 몇 명일 때는 웹 앱이 잘 작동하지만, 트래픽이 증가하면 페이지 로딩이 느려지고, 백그라운드 작업이 중복되며, API가 악의적인 클라이언트에 의해 과도하게 호출되는 문제가 발생합니다. 이러한 전형적인 확장 문제를 Redis로 우아하게 해결할 수 있습니다. Redis는 인메모리 데이터 저장소로, 세 가지 핵심 작업에 뛰어납니다: 캐싱, 큐, 속도 제한. 이 글에서는 각 사용 사례를 실용적인 예제와 모범 사례와 함께 살펴보겠습니다.

이러한 사용 사례에 Redis를 사용하는 이유

Redis는 데이터를 메모리에 저장하여 매우 빠릅니다—종종 밀리초 이하의 응답 시간을 제공합니다. 문자열, 리스트, 집합, 정렬된 집합, 해시와 같은 풍부한 데이터 구조를 지원하여 캐싱, 큐, 속도 제한에 자연스럽게 매핑됩니다. 또한 원자적 연산, 발행/구독, 지속성 옵션을 제공하여 백엔드 개발자에게 다재다능한 도구입니다.

1. Redis를 사용한 캐싱

캐싱은 가장 일반적인 Redis 사용 사례입니다. 자주 액세스하는 데이터를 Redis에 저장하면 데이터베이스 부하를 줄이고 응답 속도를 높일 수 있습니다.

캐싱 작동 방식

요청이 들어오면 Redis에 데이터가 있는지 확인합니다. 있으면(캐시 적중) 직접 반환합니다. 없으면(캐시 미스) 데이터베이스에서 가져와 만료 시간과 함께 Redis에 저장한 후 반환합니다. 이 패턴을 캐시-어사이드라고 합니다.

// ioredis를 사용한 Node.js 예제
const Redis = require('ioredis');
const redis = new Redis();

async function getUser(userId) {
  const cacheKey = `user:${userId}`;
  const cached = await redis.get(cacheKey);
  if (cached) return JSON.parse(cached);

  const user = await db.query('SELECT * FROM users WHERE id = ?', [userId]);
  await redis.set(cacheKey, JSON.stringify(user), 'EX', 3600); // 1시간 TTL
  return user;
}

캐싱 모범 사례

캐시 무효화 전략

무효화는 어렵습니다. 일반적인 전략은 다음과 같습니다:

2. Redis를 사용한 큐

큐는 시간이 많이 걸리는 작업을 요청-응답 주기에서 분리합니다. 예를 들어 이메일 보내기, 이미지 처리, 보고서 생성 등을 비동기적으로 수행할 수 있습니다.

간단한 큐 구현

Redis 리스트는 큐에 완벽합니다. LPUSH를 사용하여 왼쪽에 작업을 추가하고 BRPOP을 사용하여 오른쪽에서 블록 및 팝합니다(FIFO).

// 생산자: 작업 추가
await redis.lpush('email_queue', JSON.stringify({ to: 'user@example.com', subject: 'Welcome' }));

// 소비자: 작업 처리(워커에서)
while (true) {
  const job = await redis.brpop('email_queue', 0); // 0 = 무한 대기
  const { to, subject } = JSON.parse(job[1]);
  await sendEmail(to, subject);
}

BRPOPLPUSH를 사용한 신뢰할 수 있는 큐

워커가 충돌할 때 작업 손실을 방지하려면 BRPOPLPUSH를 사용하여 작업을 처리 목록으로 원자적으로 이동합니다. 성공적으로 처리한 후 처리 목록에서 제거합니다. 워커가 죽으면 다른 워커가 처리 목록에서 작업을 복구할 수 있습니다.

const job = await redis.brpoplpush('email_queue', 'processing_queue', 0);
try {
  // 작업 처리
  await redis.lrem('processing_queue', 1, job);
} catch (err) {
  // 오류 처리, 재큐잉 가능
}

전용 큐 라이브러리

프로덕션에서는 Bull(Node.js), RQ(Python), Sidekiq(Ruby)와 같은 라이브러리를 고려하세요. 재시도, 스케줄링, 모니터링을 기본 제공합니다.

3. Redis를 사용한 속도 제한

속도 제한은 API를 남용으로부터 보호하고 공정한 사용을 보장합니다. Redis의 원자적 연산은 요청 수를 세는 데 이상적입니다.

고정 윈도우 속도 제한

시간 창당 각 사용자에 대한 카운터를 증가시킵니다. 카운트가 제한을 초과하면 요청을 거부합니다.

async function isAllowed(userId, limit = 100, windowSec = 60) {
  const key = `rate:${userId}:${Math.floor(Date.now() / 1000 / windowSec)}`;
  const count = await redis.incr(key);
  if (count === 1) await redis.expire(key, windowSec);
  return count