본문 바로가기
IT & Tech 정보

🚀 Redis 캐시 레이어 도입: Node.js + ioredis

by 지식과 지혜의 나무 2025. 5. 25.
반응형


안녕하세요!
이번에는 Node.js 애플리케이션에 Redis를 캐시 레이어로 도입하는 방법을 단계별로 살펴보겠습니다.
ioredis 클라이언트를 사용해 간단한 캐시 구현 예제부터, TTL 설정·네임스페이스 관리·모니터링까지 실무에 바로 적용할 수 있는 코드를 제공해 드려요.



📋 목차
1. Redis 캐시 레이어란?
2. 프로젝트 초기 설정
3. ioredis 설치 및 연결
4. 기본 캐시 get·set 예제
5. TTL(만료시간) 설정 & 네임스페이스
6. 캐시 무효화 전략
7. 성능 모니터링 & 스키마 설계 팁
8. 마무리



1️⃣ Redis 캐시 레이어란?
• 목적: 빈번 조회되는 데이터(조회 결과, 세션, 설정 등)를 메모리 기반 Redis에 저장해
데이터베이스·외부 API 호출 횟수를 줄이고 응답 속도를 개선
• 장점:
• 초고속 읽기: 메모리 접근이 디스크 I/O 대비 수십 배 빠름
• 간편한 만료 관리: TTL 설정으로 자동 삭제
• 다양한 자료구조 지원: String, Hash, List, Set 등



2️⃣ 프로젝트 초기 설정

# 새 프로젝트 디렉터리 생성
mkdir node-redis-cache && cd node-redis-cache
npm init -y

# 필수 패키지 설치
npm install express ioredis dotenv
npm install --save-dev nodemon

// package.json (scripts 부분)
"scripts": {
  "start": "node index.js",
  "dev": "nodemon index.js"
}

# .env 파일 생성
echo "REDIS_HOST=127.0.0.1" >> .env
echo "REDIS_PORT=6379" >> .env
echo "REDIS_PASSWORD=" >> .env  # 비밀번호가 없다면 빈 값
echo "PORT=3000" >> .env




3️⃣ ioredis 설치 및 연결

// cache.js
require('dotenv').config();
const Redis = require('ioredis');

const redis = new Redis({
  host: process.env.REDIS_HOST,
  port: process.env.REDIS_PORT,
  password: process.env.REDIS_PASSWORD || undefined,
  retryStrategy(times) {
    // 재접속 지수 백오프 (밀리초)
    return Math.min(times * 50, 2000);
  }
});

redis.on('connect', () => console.log('✅ Redis connected'));
redis.on('error', err => console.error('❌ Redis error', err));

module.exports = redis;

• retryStrategy로 연결 실패 시 자동 재시도
• on('error') 핸들러에서 장애 감지



4️⃣ 기본 캐시 get·set 예제

// index.js
const express = require('express');
const redis = require('./cache');
const app = express();
app.use(express.json());

// 원본 데이터 조회 함수(예시)
async function fetchUserFromDB(id) {
  // DB 조회 로직 대체
  return { id, name: `user${id}`, age: 20 + id };
}

// 캐시된 사용자 정보 조회
app.get('/user/:id', async (req, res) => {
  const key = `user:${req.params.id}`;
  
  // 캐시에서 조회
  const cached = await redis.get(key);
  if (cached) {
    return res.json({ source: 'cache', data: JSON.parse(cached) });
  }

  // 캐시 미스 시 DB 조회 후 캐시에 저장
  const user = await fetchUserFromDB(req.params.id);
  await redis.set(key, JSON.stringify(user));
  res.json({ source: 'db', data: user });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`🚀 Server running on http://localhost:${PORT}`));

• redis.get(key) 후 JSON.parse,
캐시 미스 시 DB 호출→redis.set(key, JSON.stringify(value))



5️⃣ TTL(만료시간) 설정 & 네임스페이스

// 캐시에 저장할 때 TTL 60초 설정
await redis.set(key, JSON.stringify(user), 'EX', 60);

// 여러 서비스에서 충돌 방지를 위한 네임스페이스 접두사
const CACHE_PREFIX = 'myapp1:';
const keyWithNs = `${CACHE_PREFIX}user:${id}`;

// allKeys 뒤처리할 때 유용
const keys = await redis.keys(`${CACHE_PREFIX}*`);

• EX 옵션으로 초 단위 만료시간 지정
• 네임스페이스(myapp1:)를 활용해 서비스·버전 구분



6️⃣ 캐시 무효화 전략
1. 시간 기반 만료
• TTL로 자동 삭제
2. 이벤트 기반 삭제 (Cache Busting)
• 데이터 변경 시 관련 키 DEL 또는 UNLINK

// 예: 사용자 정보 수정 후 캐시 삭제
await redis.del(`${CACHE_PREFIX}user:${user.id}`);


3. LRU 정책
• Redis 서버 설정에서 maxmemory-policy allkeys-lru 사용



7️⃣ 성능 모니터링 & 스키마 설계 팁
• 모니터링
• redis INFO 명령으로 메모리 사용량·명령 통계 확인
• 외부 대시보드(RedisInsight, Grafana) 연동
• 스키마 설계
• 자주 갱신되는 데이터는 짧은 TTL
• 변경 적은 설정값은 긴 TTL 또는 무제한
• 대용량 리스트·셋 구조는 주의: 메모리 폭증 주의



8️⃣ 마무리

지금까지 ioredis를 활용한 Redis 캐시 레이어 도입 과정을 살펴봤습니다.
• 클라이언트 연결
• 기본 get·set
• TTL·네임스페이스
• 캐시 무효화 전략
• 성능 모니터링 팁

위 예제를 토대로 여러분 애플리케이션의 응답 속도와 안정성을 크게 개선해 보세요!

다음 주제에서는 Dockerfile 멀티스테이지 빌드 최적화로 찾아뵙겠습니다.

반응형