카테고리 없음
WIL - 인덱스 -> 캐시 -> Redis
그zi운아이
2025. 8. 17. 22:35
인덱스 → 캐시 → Redis
한눈에 보기
- 인덱스: 쿼리 자체를 빠르게 만드는 구조.
- 캐시: 반복 결과를 메모리에 두고 재사용해 부하/지연을 줄임.
- Redis: 캐시로도 쓰지만, 자료구조/원자연산/TTL까지 제공하는 인메모리 스토어.
인덱스 — 무엇이고 왜 쓰나
- 정의: RDB가 찾기/정렬/필터를 빠르게 하려는 자료구조(B+Tree 중심).
- 핵심 포인트
- 선택: 선두 컬럼 분포가 좋아야 스캔이 짧아짐.
- 정렬 흡수: 인덱스 순서와 ORDER BY를 맞추면 filesort 회피.
- 커버링: 필요한 컬럼이 인덱스 안에 있으면 테이블 접근 생략.
인덱스 설계 요령
- 복합 인덱스 순서 = 쿼리 의도
WHERE a=? … ORDER BY b DESC, id DESC → (a, b DESC, id DESC) - 카디널리티: BOOLEAN/NULL 등 저카디널리티 선두 금지
- 범위 조건 주의: 복합 인덱스에서 첫 범위(>, <, BETWEEN, LIKE 'p%') 이후 컬럼 활용 약화.
- Keyset(Seek) 페이징: 깊은 OFFSET 대신 다음 페이지 시작점으로 탐색.
인덱스로 안 끝나는 지점
- 깊은 페이지(OFFSET 수백~수천)
- 일부 필터+정렬 조합에서만 비싸게 튀는 케이스
- JOIN 비용 폭증(드라이빙 테이블 선택 실패 등)
- 순간 경합(스토리지/락/네트워크)
→ 여기서 캐시의 가치가 생김.
캐시 — 무엇이고 왜 쓰나
- 정의: 반복 접근 결과를 더 빠른 계층(대개 메모리)에 저장해 재사용.
- 언제 고려?
- 읽기 편향·중복 접근이 뚜렷함
- 강한 순간 일관성이 꼭 필요하진 않음(짧은 지연 허용)
- 정렬/집계/조인 비용이 큼
- 효과: 원본(DB·외부 API) 부하 절감, 평균/꼬리 지연 개선, 비용 절감.
캐시 패턴 (Cache-aside 포함, 핵심만)
- Cache-aside (앱 주도 미스 처리)
GET cache → Miss → GET DB → SET cache → 응답
단순·통제 쉬움, 프레임워크 종속 낮음. 대부분의 조회 캐시 기본값. - Read-through (캐시가 로더)
앱은 캐시만 읽고, 미스는 캐시가 직접 원본 로드 후 저장/반환.
앱 단순하지만 캐시 컴포넌트 의존·운영 복잡도↑. - Write-through (동기 쓰기)
캐시에 먼저 기록, 캐시가 즉시 DB 반영.
캐시/DB 동기화 쉬움, 대신 쓰기 레이턴시↑. - Write-back / Write-behind (지연 쓰기)
캐시에만 먼저 기록, DB는 비동기/배치 반영.
쓰기 성능↑, 장애 시 유실·불일치 리스크 관리 필요. - Refresh-ahead (선제 갱신)
만료 전에 백그라운드로 재로딩.
만료 순간 버스트 완화, 예측 빗나가면 불필요 비용.
실전 기본 조합: Cache-aside(읽기) + Write-around(쓰기 시 DB만 갱신 후 캐시 무효화) — 단순하고 예측 가능.
Redis — 무엇인가(캐시 그 이상)
- 정의: 인메모리 데이터 스토어. String/Hash/Set/ZSet/Bitmap/HLL/Geo/Stream 등 자료구조 + 원자 연산/TTL 제공.
- 자주 쓰는 용도
- 캐시(페이지/목록/상세 결과)
- 세션/토큰(만료·원자성)
- 카운팅/레이트리밋(INCR, 슬라이딩 윈도우)
- 랭킹/피드(ZSet), 가벼운 메시징(Pub/Sub, Streams)
간단 의사결정 가이드
- 쿼리 자체가 느리다 → 인덱스부터(정렬 포함, 선두 선택도, Seek 페이징)
- 반복 조회/부하가 문제다 → 캐시(패턴 선택 + 무효화 전략)
- 세션·카운트·랭킹 등 기능적 요구가 있다 → Redis 자료구조 매칭