Skip to content

junh0328/localstorage-cache-example

Repository files navigation

LocalStorage 캐시 예제

Next.js 15, TypeScript, 그리고 두 가지 통합 예제를 사용한 정교한 LocalStorage 캐시 구현으로 클라이언트 사이드 캐싱 패턴을 종합적으로 보여주는 프로젝트입니다.

🇺🇸 English Version

🎯 프로젝트 개요

이 프로젝트는 클라이언트 사이드 데이터 캐싱을 구현하는 두 가지 다른 접근 방식을 보여줍니다:

  1. 바닐라 React 구현 (/) - 수동 상태 관리와 함께 LocalStorageCache 직접 사용
  2. React Query 통합 (/react-query) - React Query의 강력한 캐싱과 영구 LocalStorage 결합

🚀 주요 기능

LocalStorageCache 유틸리티

  • 네임스페이스 격리: 별도 네임스페이스를 가진 다중 캐시 인스턴스
  • LRU 제거: 가장 최근에 사용되지 않은 항목의 자동 정리
  • 설정 가능한 리셋 스케줄: 일일, 시간별, 분 단위, 또는 커스텀 간격
  • 크기 및 항목 제한: 네임스페이스별 설정 가능한 메모리 관리
  • SSR 호환: Next.js 환경에서 localStorage의 안전한 처리
  • TypeScript 지원: 전체적인 완전한 타입 안전성

다이어그램

다이어그램

데모 애플리케이션

  • 실시간 캐시 모니터링: 실시간 통계 및 리셋 타이머
  • 인터랙티브 데이터 페칭: JSONPlaceholder API의 사용자, 게시물, 할 일 목록
  • 캐시 관리 컨트롤: 개별 또는 전체 캐시 지우기
  • 성능 비교: 바닐라 React vs React Query 패턴 나란히 비교

🛠 기술 스택

  • 프레임워크: Next.js 15 with App Router
  • 언어: TypeScript with strict mode
  • UI 라이브러리: React 19
  • 데이터 페칭: TanStack React Query + Axios
  • 패키지 매니저: pnpm
  • 개발 도구: ESLint, React Query DevTools

📦 시작하기

전제 조건

  • Node.js 18.17+ 또는 20.3+
  • pnpm (권장) 또는 npm/yarn

설치

# 리포지토리 클론
git clone https://github.com/junh0328/localstorage-cache-example.git
cd localstorage-cache-example

# 의존성 설치
pnpm install

# 개발 서버 시작
pnpm dev

바닐라 React 예제를 보려면 http://localhost:3000을, React Query 구현을 보려면 http://localhost:3000/react-query를 열어주세요.

사용 가능한 스크립트

pnpm dev          # Turbopack으로 개발 서버 시작
pnpm build        # 프로덕션 빌드 생성
pnpm start        # 프로덕션 서버 시작
pnpm lint         # ESLint 실행

🏗 아키텍처

핵심 컴포넌트

src/
├── util/
│   └── localStorageCache.ts    # 핵심 캐싱 유틸리티
├── services/
│   └── apiService.ts           # 캐시 통합이 포함된 API 레이어
├── hooks/
│   ├── useIsClient.ts          # SSR 하이드레이션 훅
│   └── useReactQueryCache.ts   # React Query + 캐시 훅
├── providers/
│   └── ReactQueryProvider.tsx  # React Query 설정
└── app/
    ├── page.tsx                # 바닐라 React 예제
    └── react-query/
        └── page.tsx            # React Query 예제

LocalStorageCache 기능

네임스페이스 관리

// 격리된 저장소를 가진 서로 다른 캐시 인스턴스
const userCache = LocalStorageCache.getInstance('users', {
  maxItemsPerKey: 50,
  reset: { type: 'hourly', value: 0 },
});

const postsCache = LocalStorageCache.getInstance('posts', {
  reset: { type: 'minutes', value: 15 },
});

리셋 전략

  • 일일: 특정 UTC 시간에 리셋 ({ type: 'daily', value: 2 })
  • 시간별: 특정 분에 리셋 ({ type: 'hourly', value: 30 })
  • 분 단위: N분마다 리셋 ({ type: 'minutes', value: 15 })
  • 커스텀: 커스텀 리셋 함수 ({ type: 'custom', customResetFn: fn })

메모리 관리

  • 항목 제한 초과 시 자동 LRU 제거
  • 저장소 제한 도달 시 크기 기반 정리
  • 네임스페이스별 설정 가능한 제한

📊 사용 예제

기본 캐시 사용법

import { LocalStorageCache } from '@/util/localStorageCache';

// 캐시 인스턴스 생성
const cache = LocalStorageCache.getInstance('my-app', {
  maxItemsPerKey: 100,
  maxTotalSize: 5 * 1024 * 1024, // 5MB
  reset: { type: 'daily', value: 1 }, // 매일 UTC 1:00에 리셋
});

// 데이터 저장
cache.set('user-123', userData);

// 데이터 조회
const user = cache.get<User>('user-123');

// 특정 데이터 지우기
cache.clearByQueryKey('user');

// 캐시 통계 가져오기
const status = cache.getStatus();

React Query 통합

import { useUsers, useClearCache } from '@/hooks/useReactQueryCache';

function UserComponent() {
  const { data: users, isLoading, error } = useUsers();
  const clearCache = useClearCache();

  const handleClearUsers = () => {
    clearCache.mutate('users');
  };

  if (isLoading) return <div>로딩 ...</div>;
  if (error) return <div>오류: {error.message}</div>;

  return (
    <div>
      {users?.map((user) => (
        <div key={user.id}>{user.name}</div>
      ))}
      <button onClick={handleClearUsers}>캐시 지우기</button>
    </div>
  );
}

🔧 설정

환경 변수

# 선택사항: 캐시 동작 커스터마이징
CACHE_SIZE=4194304              # 기본 캐시 크기 (바이트)
NODE_ENV=development            # React Query DevTools 활성화

캐시 설정

interface CacheConfig {
  namespace: string; // 필수: 고유 식별자
  maxItemsPerKey?: number; // 쿼리 키당 최대 항목 수
  maxTotalSize?: number; // 전체 최대 캐시 크기 (바이트)
  reset?: {
    type: 'daily' | 'hourly' | 'minutes' | 'custom';
    value?: number; // 시간/분/간격
    customResetFn?: (timestamp: string) => Date;
  };
}

🧪 캐시 테스트

수동 테스트

  1. 데이터 로드: 페치 버튼을 클릭하여 캐시 채우기
  2. 캐시 히트 확인: 후속 클릭은 캐시에서 즉시 로드되어야 함
  3. 저장소 모니터링: 브라우저 DevTools → Application → Local Storage 확인
  4. 만료 테스트: 리셋 시간 대기 또는 수동으로 캐시 지우기
  5. 성능 비교: 바닐라와 React Query 예제 간 전환

캐시 동작 검증

  • 브라우저 DevTools: 네임스페이스 접두사가 있는 localStorage 키 검사
  • 콘솔 로그: 캐시 히트 vs API 호출이 로깅됨
  • 네트워크 탭: 캐시 히트 시 감소된 네트워크 요청 확인
  • React Query DevTools: 쿼리 상태 및 캐시 무효화 모니터링

🚦 성능 고려사항

번들 크기

  • 프로덕션 빌드는 React Query DevTools 제외
  • LocalStorageCache 유틸리티는 경량 (~15KB 압축)
  • 비필수 캐시 인스턴스에 대한 지연 로딩 고려

메모리 사용량

  • 전체 캐시 크기 제한 모니터링
  • 적절한 maxItemsPerKey 값 사용
  • 중요한 데이터에 대한 캐시 워밍 전략 고려

네트워크 최적화

  • 적절한 stale-while-revalidate 패턴 구현
  • React Query의 백그라운드 리페칭 사용
  • 사용자 상호작용 시 프리페칭 고려

🤝 기여하기

  1. 리포지토리 포크
  2. 기능 브랜치 생성 (git checkout -b feature/amazing-feature)
  3. 변경사항 커밋 (git commit -m 'Add amazing feature')
  4. 브랜치에 푸시 (git push origin feature/amazing-feature)
  5. Pull Request 열기

📝 라이선스

이 프로젝트는 MIT 라이선스 하에 있습니다 - 자세한 내용은 LICENSE 파일을 참조하세요.

🙏 감사의 말

About

로컬 스토리지 캐싱 시스템 구축

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published