TypeScript

Node-Cache : 서버 성능 최적화

코샵 2025. 2. 17. 10:26
반응형

Node-Cache는 Node.js 애플리케이션에서 메모리 캐싱을 구현할 수 있게 해주는 간단하고 강력한 모듈입니다. 데이터베이스 쿼리 결과나 API 응답을 캐싱하여 애플리케이션의 성능을 향상시킬 수 있습니다.

기본 설치 및 설정

const NodeCache = require('node-cache');

// 기본 캐시 인스턴스 생성
const cache = new NodeCache({
    stdTTL: 600, // 기본 TTL 10분
    checkperiod: 120 // 만료된 항목 점검 주기 2분
});

기본적인 캐시 사용법

// 데이터 저장
cache.set('user:123', { name: 'John', age: 30 });

// 데이터 조회
const data = cache.get('user:123');

// 여러 키 한번에 조회
const multiData = cache.mget(['user:123', 'user:124']);

// 데이터 삭제
cache.del('user:123');

FastAPI와 함께 사용하기

const express = require('express');
const NodeCache = require('node-cache');
const app = express();
const cache = new NodeCache();

app.get('/users/:id', async (req, res) => {
    const { id } = req.params;
    const cacheKey = `user:${id}`;

    // 캐시 확인
    const cachedData = cache.get(cacheKey);
    if (cachedData) {
        return res.json(cachedData);
    }

    // DB 조회
    try {
        const user = await database.getUser(id);
        // 캐시에 저장
        cache.set(cacheKey, user, 3600); // 1시간 캐시
        res.json(user);
    } catch (error) {
        res.status(500).json({ error: 'Server error' });
    }
});

고급 캐시 패턴

// 캐시 미들웨어
const cacheMiddleware = (duration) => {
    return (req, res, next) => {
        const key = `__cache__${req.originalUrl}`;
        const cachedResponse = cache.get(key);

        if (cachedResponse) {
            res.json(cachedResponse);
            return;
        }

        res.originalJson = res.json;
        res.json = (body) => {
            cache.set(key, body, duration);
            res.originalJson(body);
        };
        next();
    };
};

// 사용 예시
app.get('/popular-posts', cacheMiddleware(300), async (req, res) => {
    const posts = await getPosts();
    res.json(posts);
});

캐시 이벤트 처리

// 캐시 만료 이벤트
cache.on('expired', (key, value) => {
    console.log(`Cache key ${key} has expired`);
    // 필요한 정리 작업 수행
});

// 캐시 삭제 이벤트
cache.on('del', (key, value) => {
    console.log(`Cache key ${key} was deleted`);
});

// 캐시 설정 이벤트
cache.on('set', (key, value) => {
    console.log(`New cache entry: ${key}`);
});

패턴별 캐시 구현

데이터베이스 쿼리 캐싱

class CachedDatabase {
    constructor() {
        this.cache = new NodeCache({ stdTTL: 3600 });
    }

    async getUser(id) {
        const cacheKey = `user:${id}`;
        let user = this.cache.get(cacheKey);

        if (!user) {
            user = await database.findUser(id);
            this.cache.set(cacheKey, user);
        }

        return user;
    }

    invalidateUser(id) {
        this.cache.del(`user:${id}`);
    }
}

API 응답 캐싱

class ApiCache {
    constructor() {
        this.cache = new NodeCache({
            stdTTL: 600,
            checkperiod: 60
        });
    }

    async fetchWithCache(url, options = {}) {
        const cacheKey = this.generateKey(url, options);
        let data = this.cache.get(cacheKey);

        if (!data) {
            const response = await fetch(url, options);
            data = await response.json();
            this.cache.set(cacheKey, data);
        }

        return data;
    }

    generateKey(url, options) {
        return `${options.method || 'GET'}:${url}`;
    }
}

성능 모니터링

class CacheMonitor {
    constructor(cache) {
        this.cache = cache;
        this.stats = {
            hits: 0,
            misses: 0
        };

        this.setupMonitoring();
    }

    setupMonitoring() {
        // 캐시 히트 모니터링
        const originalGet = this.cache.get;
        this.cache.get = (...args) => {
            const value = originalGet.apply(this.cache, args);
            value ? this.stats.hits++ : this.stats.misses++;
            return value;
        };
    }

    getStats() {
        const hitRate = this.stats.hits / (this.stats.hits + this.stats.misses);
        return {
            ...this.stats,
            hitRate: hitRate || 0
        };
    }
}

 

주의사항

  1. 메모리 사용량
    • 적절한 TTL 설정
    • 주기적인 캐시 정리
  2. 캐시 무효화
    • 데이터 업데이트 시 관련 캐시 삭제
    • 일관성 유지
  3. 동시성 처리
    • Race condition 방지
    • 락 메커니즘 고려
  4. 모니터링
    • 캐시 히트율 추적
    • 메모리 사용량 감시

Node-Cache는 간단하면서도 강력한 캐싱 솔루션을 제공합니다. 적절히 활용하면 애플리케이션의 성능을 크게 향상시킬 수 있습니다.