Redis가 내 데이터베이스 읽기를 ~26K에서 거의 0으로 줄인 방법
Source: Dev.to

나는 페이지를 로드할 때마다 Supabase에 요청을 하곤 했습니다—블로그, 개별 포스트, 경험, 툴박스, 서비스, 연결, 프로필 정보, 역할 가시성, 스킬… 기본적으로 내 개인 대시보드 전체가 직접 데이터베이스 쿼리에 의존하고 있었습니다.
그 결과는?
- 하루에 약 26,000번의 데이터베이스 읽기
- 느린 응답
- 불필요한 부하
- 가끔 발생하는 연결 경고
그래서 저는 작은 pre‑warm 스크립트와 함께 읽기‑통과 캐시로서 Redis를 도입했습니다—그리고 모든 것이 바뀌었습니다.
내가 캐시한 내용
나는 가장 읽기 집중적인 데이터에 초점을 맞췄다:
- Blogs → published list, per‑post data, combined blog payload → 블로그 → 게시된 목록, 포스트별 데이터, 결합된 블로그 페이로드
- Experiences → active + full history → 경험 → 활성 + 전체 기록
- Toolboxes → all, software, hardware → 툴박스 → 전체, 소프트웨어, 하드웨어
- Services → active + all → 서비스 → 활성 + 전체
- Connections → full list → 연결 → 전체 목록
- Profile info → singleton record → 프로필 정보 → 단일 레코드
- Role visibility → sidebar & quick actions → 역할 가시성 → 사이드바 및 빠른 작업
- Skills → full list + category variants → 스킬 → 전체 목록 + 카테고리 변형
이것들은 완벽한 캐시 후보였으며, 이유는:
- 자주 변경되지 않음
- 지속적으로 읽힘
- 실시간 일관성이 필요 없음
캐싱 작동 방식
1) 읽기‑통과 캐시 패턴
각 GET 엔드포인트는 다음 헬퍼를 감쌉니다:
getCached(key, fetcher, ttl = 300)
Flow
Request → Check Redis
→ Cache hit → return instantly
→ Cache miss → fetch from Supabase → store in Redis → return
- 첫 번째 요청만 DB에 접근합니다
- 나머지 모든 요청은 밀리초 단위로 Redis에서 제공됩니다
2) 쓰기 시 스마트 무효화
데이터가 POST, PUT, 혹은 DELETE 로 변경될 때마다 다음을 호출합니다:
invalidateKeys([...])
이는 영향을 받은 캐시 프리픽스만 삭제하여 다음을 유지합니다:
- 신선함
- 일관성
- 빠른 응답
3) 캐시 사전 가열
배포 후 콜드‑스타트 지연을 방지하기 위해 다음 스크립트를 만들었습니다:
scripts/prewarm-redis.mjs
이 스크립트는 공개 API 엔드포인트만 호출하므로 DB 자격 증명이 필요 없습니다.
실행 방법은 다음과 같습니다:
BASE_URL=http://localhost:3000 node scripts/prewarm-redis.mjs
이제 실제 사용자가 접속하기 전에 Redis가 완전히 채워집니다.
4) 가시성 및 상태 모니터링
Data 탭 UI를 추가하여 다음을 표시합니다:
- Redis 상태 확인
- 전체 캐시 항목 수
- 캐시된 데이터셋 개요
Redis가 다운되면 즉시 알 수 있습니다.
결과 📉
Redis 이전
- ~26K DB 읽기/일
- 높은 지연 시간
- 최대 연결 제한 위험
Redis 이후
- 콜드 스타트: 데이터셋당 DB 접근 1회
- 워밍 트래픽: 거의 DB 읽기 없음
- 지연 시간: 한 자릿수 밀리초
- 안정성: 연결 압력 없음
요약: 데이터베이스는 백업이 되었고, Redis가 주요 읽기 레이어가 되었습니다.
가장 큰 차이를 만든 요소
- 가장 많이 읽히는 데이터를 캐시 – 리스트와 싱글톤 데이터는 캐시할 때 막대한 ROI를 제공합니다.
- TTL을 적당히 유지 – 5분을 사용하여 신선도와 성능의 균형을 맞췄습니다.
- 배포 시 항상 프리웜 – 콜드‑스타트 패널티를 완전히 제거합니다.
- 캐시 상태 모니터링 – 가시성을 확보해 조용한 성능 저하를 방지합니다.
어떻게 시도할 수 있나요
-
Redis 구성
REDIS_URL=... # or host/port/user/password -
앱 시작
-
프리웜 스크립트 실행
-
대시보드/블로그 페이지 열기
관찰:
- DB 메트릭 감소
- Redis 히트 비율 상승
- 지연 시간 감소
최종 생각
Redis를 추가하는 것은 단순한 성능 최적화가 아니라, 내 앱이 대규모 읽기를 처리하는 방식을 근본적으로 바꾸었습니다.
From:
“매번 데이터베이스를 조회한다”
to:
“메모리에서 즉시 제공하고, 필요할 때만 DB에 접근한다.”
그 단 한 번의 변화로 일일 26K 읽기를 거의 제로에 가깝게 줄였습니다.
그리고 가장 좋은 점은? 구현에 하루도 채 걸리지 않았습니다.