Redis 완벽 마스터

Redis의 핵심 개념과 실전 활용법

JavaScript중급
10시간
5개 항목
학습 진행률0 / 5 (0%)

학습 항목

1. JavaScript
중급
Caching|기초부터|심화까지|완벽|가이드
퀴즈튜토리얼
2. JavaScript
중급
Caching|베스트|프랙티스|완벽|가이드
퀴즈튜토리얼
3. JavaScript
Redis|캐싱|완벽|가이드
퀴즈튜토리얼
4. JavaScript
고급
Redis|테스트|전략|완벽|가이드
퀴즈튜토리얼
5. Python
고급
Redis|핵심|개념|완벽|정리
퀴즈튜토리얼
1 / 5

이미지 로딩 중...

Caching 기초부터 심화까지 완벽 가이드 - 슬라이드 1/13

Caching 기초부터 심화까지 완벽 가이드

캐싱의 기본 개념부터 실전 활용까지 단계별로 학습합니다. 메모리 캐싱, Redis 활용, 캐시 무효화 전략 등 실무에서 바로 적용 가능한 캐싱 기법을 다룹니다.


카테고리:JavaScript
언어:JavaScript
난이도:intermediate
메인 태그:#JavaScript
서브 태그:
#Caching#Redis#Memoization#Performance

들어가며

이 글에서는 Caching 기초부터 심화까지 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.

목차

  1. 기본_메모리_캐싱
  2. Memoization_패턴
  3. LRU_캐시_구현
  4. TTL_기반_캐시
  5. Redis_기본_캐싱
  6. Cache_Aside_패턴
  7. Write_Through_캐싱
  8. 캐시_무효화_전략
  9. 다중_레벨_캐싱
  10. Cache_Stampede_방지
  11. 조건부_캐싱
  12. Pub_Sub_캐시_동기화

1. 기본_메모리_캐싱

개요

간단한 객체를 사용하여 함수 결과를 메모리에 캐싱하는 기본 패턴입니다.

코드 예제

const cache = {};

function expensiveCalculation(n) {
  if (cache[n]) return cache[n];

  const result = n * n; // 실제로는 복잡한 연산
  cache[n] = result;
  return result;
}

console.log(expensiveCalculation(5)); // 25

설명

계산 결과를 객체에 저장하여 동일한 입력에 대해 재계산을 방지합니다. 캐시 히트 시 즉시 결과를 반환합니다.


2. Memoization_패턴

개요

고차 함수를 사용하여 어떤 함수든 메모이제이션을 적용할 수 있는 범용 패턴입니다.

코드 예제

function memoize(fn) {
  const cache = {};
  return function(...args) {
    const key = JSON.stringify(args);
    if (cache[key]) return cache[key];

    const result = fn(...args);
    cache[key] = result;
    return result;
  };
}

const fibonacci = memoize((n) =>
  n <= 1 ? n : fibonacci(n-1) + fibonacci(n-2)
);

설명

함수를 감싸서 자동으로 결과를 캐싱합니다. 인자를 문자열로 변환하여 캐시 키로 사용합니다.


3. LRU_캐시_구현

개요

최근 사용 빈도 기반으로 캐시를 관리하는 LRU(Least Recently Used) 알고리즘 구현입니다.

코드 예제

class LRUCache {
  constructor(limit) {
    this.cache = new Map();
    this.limit = limit;
  }

  get(key) {
    if (!this.cache.has(key)) return null;
    const value = this.cache.get(key);
    this.cache.delete(key);
    this.cache.set(key, value); // 최신으로 이동
    return value;
  }

  set(key, value) {
    if (this.cache.has(key)) this.cache.delete(key);
    else if (this.cache.size >= this.limit) {
      this.cache.delete(this.cache.keys().next().value);
    }
    this.cache.set(key, value);
  }
}

설명

Map을 사용하여 삽입 순서를 유지하고, 용량 초과 시 가장 오래된 항목을 자동으로 제거합니다.


4. TTL_기반_캐시

개요

시간 제한(Time To Live)을 적용하여 일정 시간 후 캐시가 자동으로 만료되도록 합니다.

코드 예제

class TTLCache {
  constructor(ttl = 60000) {
    this.cache = new Map();
    this.ttl = ttl;
  }

  set(key, value) {
    const expiry = Date.now() + this.ttl;
    this.cache.set(key, { value, expiry });
  }

  get(key) {
    const item = this.cache.get(key);
    if (!item) return null;
    if (Date.now() > item.expiry) {
      this.cache.delete(key);
      return null;
    }
    return item.value;
  }
}

설명

각 캐시 항목에 만료 시간을 저장하고, 조회 시 만료 여부를 확인하여 자동으로 삭제합니다.


5. Redis_기본_캐싱

개요

Redis를 사용한 분산 캐싱으로 여러 서버 간 캐시를 공유합니다.

코드 예제

const redis = require('redis');
const client = redis.createClient();

async function getCachedData(key) {
  const cached = await client.get(key);
  if (cached) return JSON.parse(cached);

  const data = await fetchFromDB(key);
  await client.setEx(key, 3600, JSON.stringify(data));
  return data;
}

async function fetchFromDB(key) {
  return { id: key, name: 'example' };
}

설명

Redis에서 데이터를 조회하고, 없으면 DB에서 가져온 후 1시간 TTL로 캐싱합니다.


6. Cache_Aside_패턴

개요

애플리케이션이 캐시를 직접 관리하는 가장 일반적인 캐싱 전략입니다.

코드 예제

async function getData(userId) {
  // 1. 캐시 확인
  let user = await cache.get(`user:${userId}`);

  if (user) return user;

  // 2. DB에서 조회
  user = await db.users.findById(userId);

  // 3. 캐시에 저장
  await cache.set(`user:${userId}`, user, 3600);

  return user;
}

설명

캐시 미스 시 DB에서 조회 후 캐시에 저장합니다. 가장 유연하지만 캐시와 DB 동기화를 신경 써야 합니다.


7. Write_Through_캐싱

개요

데이터 쓰기 시 캐시와 DB에 동시에 저장하여 항상 동기화 상태를 유지합니다.

코드 예제

async function updateUser(userId, userData) {
  // 1. DB 업데이트
  const updatedUser = await db.users.update(
    userId,
    userData
  );

  // 2. 캐시 업데이트
  await cache.set(
    `user:${userId}`,
    updatedUser,
    3600
  );

  return updatedUser;
}

설명

쓰기 작업 시 캐시와 DB를 동시에 업데이트하여 데이터 일관성을 보장합니다.


8. 캐시_무효화_전략

개요

데이터 변경 시 관련된 캐시를 삭제하여 오래된 데이터 제공을 방지합니다.

코드 예제

async function deleteUser(userId) {
  // 1. DB에서 삭제
  await db.users.delete(userId);

  // 2. 관련 캐시 무효화
  await cache.del(`user:${userId}`);
  await cache.del(`user:${userId}:posts`);
  await cache.del(`user:${userId}:profile`);

  return { success: true };
}

설명

데이터 삭제 또는 수정 시 관련된 모든 캐시 키를 명시적으로 삭제하여 정합성을 유지합니다.


9. 다중_레벨_캐싱

개요

메모리 캐시와 Redis를 조합하여 2단계 캐싱 전략을 구현합니다.

코드 예제

const localCache = new Map();

async function getWithMultiLevel(key) {
  // L1: 로컬 메모리 캐시
  if (localCache.has(key)) return localCache.get(key);

  // L2: Redis 캐시
  const redisData = await redis.get(key);
  if (redisData) {
    localCache.set(key, redisData);
    return redisData;
  }

  // L3: DB
  const data = await db.get(key);
  await redis.setEx(key, 3600, data);
  localCache.set(key, data);
  return data;
}

설명

로컬 메모리(빠름) → Redis(중간) → DB(느림) 순서로 조회하여 최적의 성능을 제공합니다.


10. Cache_Stampede_방지

개요

동시에 많은 요청이 캐시 미스를 일으킬 때 DB 과부하를 방지하는 패턴입니다.

코드 예제

const loading = new Map();

async function getDataSafe(key) {
  const cached = await cache.get(key);
  if (cached) return cached;

  if (loading.has(key)) {
    return await loading.get(key);
  }

  const promise = fetchAndCache(key);
  loading.set(key, promise);
  const result = await promise;
  loading.delete(key);
  return result;
}

async function fetchAndCache(key) {
  const data = await db.get(key);
  await cache.set(key, data, 3600);
  return data;
}

설명

동일한 키에 대한 중복 요청을 Promise로 그룹화하여 DB에는 한 번만 요청합니다.


11. 조건부_캐싱

개요

특정 조건을 만족하는 데이터만 선택적으로 캐싱하여 메모리를 효율적으로 사용합니다.

코드 예제

async function smartCache(userId) {
  const user = await db.users.findById(userId);

  // 활성 사용자만 캐싱
  if (user.isActive && user.lastLogin > Date.now() - 86400000) {
    await cache.set(
      `user:${userId}`,
      user,
      7200
    );
  }

  return user;
}

설명

자주 조회되는 활성 사용자만 캐싱하여 캐시 메모리를 효율적으로 활용합니다.


12. Pub_Sub_캐시_동기화

개요

Redis Pub/Sub을 사용하여 여러 서버 간 캐시 무효화 이벤트를 동기화합니다.

코드 예제

const subscriber = redis.createClient();
const publisher = redis.createClient();

subscriber.subscribe('cache:invalidate');
subscriber.on('message', (channel, key) => {
  localCache.delete(key);
});

async function invalidateCache(key) {
  await cache.del(key);
  await publisher.publish('cache:invalidate', key);
  localCache.delete(key);
}

설명

한 서버에서 캐시를 무효화하면 모든 서버의 로컬 캐시도 함께 삭제되어 일관성을 유지합니다.


마치며

이번 글에서는 Caching 기초부터 심화까지 완벽 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.

관련 태그

#JavaScript #Caching #Redis #Memoization #Performance

#JavaScript#Caching#Redis#Memoization#Performance