Redis 실전 가이드
Redis의 핵심 개념과 실무 활용
학습 항목
본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
이미지 로딩 중...
Redis 캐싱 완벽 가이드
Redis를 활용한 효율적인 캐싱 전략과 고급 기법을 다룹니다. 캐시 무효화, TTL 관리, 분산 캐싱 패턴 등 실무에서 필요한 핵심 개념들을 실제 코드와 함께 학습할 수 있습니다.
들어가며
이 글에서는 Redis 캐싱 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.
목차
- 기본_Redis_캐싱_설정
- Cache-Aside_패턴
- Write-Through_캐싱
- 캐시_무효화_전략
- Redis_Pipeline_최적화
- 분산_락_구현
- 캐시_워밍업
- 스마트_TTL_관리
- 캐시_태깅_시스템
- Pub_Sub_캐시_동기화
- 레이트_리미팅_캐시
- 캐시_통계_모니터링
1. 기본 Redis 캐싱 설정
개요
Redis 클라이언트를 설정하고 기본적인 캐싱 패턴을 구현합니다. 데이터를 캐시에 저장하고 조회하는 기본 플로우를 보여줍니다.
코드 예제
const redis = require('redis');
const client = redis.createClient();
async function getUser(userId) {
const cached = await client.get(`user:${userId}`);
if (cached) return JSON.parse(cached);
const user = await db.findUser(userId);
await client.setEx(`user:${userId}`, 3600, JSON.stringify(user));
return user;
}
설명
캐시에서 데이터를 먼저 확인하고, 없으면 DB에서 가져온 후 1시간(3600초) TTL로 캐시에 저장합니다.
2. Cache-Aside 패턴
개요
가장 일반적인 캐싱 패턴으로, 애플리케이션이 캐시를 직접 관리합니다. 캐시 미스 시 DB에서 데이터를 가져와 캐시를 업데이트합니다.
코드 예제
async function getData(key) {
let data = await cache.get(key);
if (!data) {
data = await database.query(key);
await cache.set(key, data, { EX: 600 });
}
return data;
}
설명
캐시에 없으면 DB 조회 후 10분간 캐시에 저장하는 Lazy Loading 방식입니다.
3. Write-Through 캐싱
개요
데이터 쓰기 시 캐시와 DB를 동시에 업데이트하여 캐시와 DB의 일관성을 보장합니다. 읽기 성능이 중요한 경우 유용합니다.
코드 예제
async function updateUser(userId, data) {
await db.update(userId, data);
await client.set(
`user:${userId}`,
JSON.stringify(data),
{ EX: 3600 }
);
return data;
}
설명
DB 업데이트와 동시에 캐시도 갱신하여 항상 최신 데이터를 캐시에 유지합니다.
4. 캐시 무효화 전략
개요
데이터가 변경될 때 관련된 모든 캐시를 삭제하여 stale 데이터를 방지합니다. 패턴 매칭을 사용한 일괄 삭제가 가능합니다.
코드 예제
async function invalidateUserCache(userId) {
const keys = await client.keys(`user:${userId}:*`);
if (keys.length > 0) {
await client.del(keys);
}
await client.del(`user:${userId}`);
}
설명
특정 사용자와 관련된 모든 캐시 키를 찾아서 삭제하여 데이터 일관성을 유지합니다.
5. Redis Pipeline 최적화
개요
여러 Redis 명령을 하나의 네트워크 요청으로 묶어서 실행합니다. 대량의 캐시 작업 시 성능을 크게 향상시킵니다.
코드 예제
async function cacheMultipleUsers(users) {
const pipeline = client.pipeline();
users.forEach(user => {
pipeline.setEx(`user:${user.id}`, 3600, JSON.stringify(user));
});
await pipeline.exec();
}
설명
여러 SET 명령을 파이프라인으로 묶어서 한 번에 실행하여 네트워크 왕복 시간을 줄입니다.
6. 분산 락 구현
개요
분산 환경에서 동시성 문제를 해결하기 위한 락 메커니즘입니다. Redis의 원자적 연산을 활용하여 안전한 락을 구현합니다.
코드 예제
async function acquireLock(lockKey, timeout = 10) {
const lockValue = Date.now() + timeout * 1000;
const acquired = await client.set(
lockKey, lockValue, { NX: true, EX: timeout }
);
return acquired ? lockValue : null;
}
설명
NX 옵션으로 키가 없을 때만 설정하여 원자적 락을 획득하고, TTL로 데드락을 방지합니다.
7. 캐시 워밍업
개요
애플리케이션 시작 시 자주 사용되는 데이터를 미리 캐시에 로드합니다. Cold start 시의 성능 저하를 방지합니다.
코드 예제
async function warmupCache() {
const popularItems = await db.getPopularItems(100);
for (const item of popularItems) {
await client.setEx(
`item:${item.id}`, 7200, JSON.stringify(item)
);
}
}
설명
인기 있는 데이터를 미리 2시간 TTL로 캐시에 저장하여 초기 요청부터 빠른 응답을 제공합니다.
8. 스마트 TTL 관리
개요
데이터 특성에 따라 동적으로 TTL을 설정합니다. 자주 조회되는 데이터는 더 긴 TTL을 부여하여 캐시 효율을 높입니다.
코드 예제
async function setWithSmartTTL(key, value, accessCount) {
const baseTTL = 300;
const ttl = baseTTL + Math.min(accessCount * 60, 3600);
await client.setEx(key, ttl, JSON.stringify(value));
await client.incr(`${key}:access`);
}
설명
접근 횟수에 따라 TTL을 동적으로 조정하여 인기 데이터는 더 오래 캐시에 유지합니다.
9. 캐시 태깅 시스템
개요
관련된 캐시들을 태그로 그룹화하여 효율적으로 관리합니다. 특정 태그의 모든 캐시를 한 번에 무효화할 수 있습니다.
코드 예제
async function cacheWithTags(key, value, tags) {
await client.set(key, value);
for (const tag of tags) {
await client.sAdd(`tag:${tag}`, key);
}
}
async function invalidateByTag(tag) {
const keys = await client.sMembers(`tag:${tag}`);
if (keys.length) await client.del(keys);
}
설명
Set 자료구조로 태그별 키를 관리하여, 카테고리별 일괄 캐시 삭제가 가능합니다.
10. Pub Sub 캐시 동기화
개요
여러 서버 인스턴스 간 캐시를 동기화합니다. 한 서버에서 캐시 무효화 시 다른 서버들도 자동으로 업데이트됩니다.
코드 예제
const subscriber = redis.createClient();
subscriber.subscribe('cache:invalidate');
subscriber.on('message', (channel, key) => {
localCache.delete(key);
});
async function invalidateGlobal(key) {
await client.publish('cache:invalidate', key);
}
설명
Redis Pub/Sub으로 캐시 무효화 이벤트를 브로드캐스트하여 분산 환경에서 캐시 일관성을 유지합니다.
11. 레이트 리미팅 캐시
개요
Redis를 활용한 API 요청 제한 구현입니다. 시간 윈도우 내 요청 횟수를 추적하여 과도한 요청을 차단합니다.
코드 예제
async function checkRateLimit(userId, limit = 100) {
const key = `ratelimit:${userId}:${Date.now() / 60000 | 0}`;
const current = await client.incr(key);
if (current === 1) await client.expire(key, 60);
return current <= limit;
}
설명
분당 요청 횟수를 카운트하고 1분 후 자동 삭제되어, 간단하고 효율적인 레이트 리미팅을 구현합니다.
12. 캐시 통계 모니터링
개요
캐시 히트율과 성능 지표를 추적합니다. 캐시 효율성을 측정하고 최적화 포인트를 찾는데 활용합니다.
코드 예제
async function getCacheStats() {
const info = await client.info('stats');
const hits = parseInt(info.match(/keyspace_hits:(\d+)/)[1]);
const misses = parseInt(info.match(/keyspace_misses:(\d+)/)[1]);
const hitRate = (hits / (hits + misses) * 100).toFixed(2);
return { hits, misses, hitRate: `${hitRate}%` };
}
설명
Redis의 통계 정보를 파싱하여 캐시 히트율을 계산하고 캐시 전략의 효과를 측정합니다.
마치며
이번 글에서는 Redis 캐싱 완벽 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.
관련 태그
#Redis #Caching #TTL #CacheInvalidation #DistributedCache