Redis 실전 가이드
Redis의 핵심 개념과 실무 활용
학습 항목
이미지 로딩 중...
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