TIL2026. 8. 18.

캐시 개념 정리

#개념

캐시란

같은 데이터를 반복 요청하지 않도록 결과를 저장해두는 것. 어디에, 얼마나, 누구 기준으로 저장하느냐에 따라 종류가 나뉨.


1. 브라우저 캐시 (Client-side)

브라우저가 로컬 디스크에 저장. 개인 단위.

1-1. HTTP 캐시 (디스크/메모리 캐시)

서버 응답 헤더(Cache-Control, ETag, Last-Modified)에 따라 브라우저가 자동 저장.

Cache-Control: max-age=3600 → 1시간 동안 서버 요청 안 함 Cache-Control: no-cache → 매번 서버에 유효성 확인 Cache-Control: no-store → 아예 저장 안 함
  • 같은 이미지, JS, CSS 반복 다운로드 방지
  • ETag: 파일 해시. 서버에 "이거 바뀌었어?" 물어봄 → 안 바뀌었으면 304 응답 (본문 없음)
  • 강력 새로고침(Ctrl+Shift+R): 이 캐시 무시하고 서버에 새로 요청

1-2. Service Worker 캐시

개발자가 JS로 직접 제어하는 캐시. Cache API 사용.

// 설치 시 정적 자산 미리 캐시 self.addEventListener('install', (e) => { e.waitUntil( caches.open('v1').then((cache) => cache.addAll(['/index.html', '/style.css']) ) ); });
  • 오프라인 지원 가능 (PWA)
  • 네트워크 요청 가로채서 캐시 우선/네트워크 우선 전략 선택
  • 브라우저 캐시와 달리 만료 정책을 코드로 완전 제어

1-3. 메모리 캐시 (JS 런타임)

변수, Map, 상태에 저장. 탭 닫으면 사라짐.

const cache = new Map(); function getData(key) { if (cache.has(key)) return cache.get(key); const data = fetchFromAPI(key); cache.set(key, data); return data; }
  • React Query, SWR 등이 이 방식. API 응답을 메모리에 캐시하고 stale 시간 관리.

2. 서버/CDN 캐시 (Server-side)

서버 또는 CDN이 저장. 모든 유저 공유.

2-1. CDN 캐시 (Edge 캐시)

전 세계 엣지 서버에 응답 복사본 저장. Vercel, Cloudflare 등.

유저 (서울) → 도쿄 엣지 → 캐시 있음 → 즉시 응답 (오리진 서버 안 감) 유저 (LA) → SF 엣지 → 캐시 있음 → 즉시 응답
  • 모든 유저가 같은 캐시 공유
  • 지리적으로 가까운 엣지에서 서빙 → 빠름
  • 오리진 서버 부하 0

2-2. ISR 캐시 (Incremental Static Regeneration)

Next.js 전용 개념. CDN 캐시 + 백그라운드 재생성 결합.

export const revalidate = 43200; // 12시간

동작 흐름:

[0초] 첫 요청 → 서버 렌더링 → HTML 생성 → CDN 저장 → 유저에게 응답 [1~12h] 모든 요청 → CDN 캐시 서빙 (서버 실행 0) [12h] 캐시 만료 → 요청 오면: 1. stale 캐시 먼저 서빙 (유저는 빠르게 받음) 2. 백그라운드에서 서버 재렌더링 3. 새 HTML로 CDN 캐시 교체 [12h+] 다음 요청부터 새 캐시 서빙

핵심 특징:

  • 유저가 느린 응답 받는 순간 = 배포 직후 첫 요청 딱 1번
  • 만료 후에도 stale 캐시 먼저 보여줌 (느린 응답 없음)
  • revalidatePath() / revalidateTag()로 수동 갱신 가능

2-3. SSR 캐시 없음 (force-dynamic)

export const dynamic = "force-dynamic";

매 요청마다 서버 함수 실행. 캐시 안 함.

유저A 요청 → 서버 실행 → DB 조회 → 렌더링 → 응답 유저B 요청 → 서버 실행 → DB 조회 → 렌더링 → 응답 (똑같은 작업 반복)
  • 항상 최신 데이터
  • 서버 부하 비례 증가

2-4. SSG (Static Site Generation)

빌드 시점에 HTML 생성. 배포 후 변하지 않음.

빌드 시 → HTML 생성 → CDN에 배포 → 재배포 전까지 동일
  • 가장 빠름 (완전 정적)
  • 데이터 변경 반영 = 재빌드 필요

2-5. 서버 메모리/Redis 캐시

서버 애플리케이션 레벨에서 DB 쿼리 결과 등을 메모리나 Redis에 저장.

요청 → Redis에 캐시 있음? → 있으면 반환 / 없으면 DB 조회 후 저장
  • DB 부하 감소
  • TTL(Time To Live) 설정으로 자동 만료
  • Vercel Serverless에서는 함수 인스턴스 간 메모리 공유 안 되므로 Redis(Upstash 등) 필요

3. DNS 캐시

도메인 → IP 변환 결과를 OS/브라우저/라우터가 저장.

dolchimdae.vercel.app → 76.76.21.21 (캐시됨, DNS 서버 안 감)
  • TTL 보통 수 분~수 시간
  • ipconfig /flushdns (Windows)로 초기화

4. DB 캐시 (Query Cache)

데이터베이스 자체가 쿼리 결과 캐시. PostgreSQL의 shared_buffers, MySQL의 Query Cache 등.

같은 SELECT → 디스크 안 읽고 메모리에서 반환
  • 개발자가 직접 제어할 일 적음
  • Supabase(PostgreSQL) 자체적으로 동작

비교 요약

캐시 종류저장 위치공유 범위제어 방법무효화
브라우저 HTTP유저 디스크개인Cache-Control 헤더강력새로고침, 시간만료
Service Worker유저 디스크개인JS 코드코드로 삭제
메모리 (SWR 등)유저 RAM개인 (탭)라이브러리 설정탭 닫기, refetch
CDN/Edge엣지 서버전체 유저서버 헤더퍼지, 재배포
ISRVercel CDN전체 유저revalidate 값시간만료, revalidatePath
SSGCDN전체 유저빌드 시 생성재빌드
Redis서버 메모리전체 요청TTL, 코드TTL 만료, DEL 명령
DNSOS/라우터개인/네트워크TTLflushdns
DB QueryDB 메모리전체 쿼리DB 설정데이터 변경 시 자동

현재 프로젝트 적용 상태

/job-radar → ISR 12시간 (CDN 캐시, 전체 유저 공유) /job-radar/saved → ISR 12시간 /job-radar/gap → ISR 12시간 /job-radar/[id] → 동적 (매 요청 서버 실행) /blog, /projects → ISR (빌드 시 설정값 따름)

캐시 레이어 순서 (요청 흐름):

브라우저 캐시 → CDN/ISR 캐시 → Serverless Function → Supabase (DB 캐시) 개인용 전체 공유 서버 실행 DB 레벨

각 레이어에서 캐시 히트하면 그 아래로 안 감. ISR에서 히트하면 서버 함수 실행 자체가 없음.

요즘 작업송