캐싱·Redis — 백엔드 면접 (실제 기출 기반·심화)
"캐시 전략", "캐시 무효화", "Redis 자료구조", "캐시 스탬피드", "분산 락을 Redis로", "Redis는 왜 빠른가" — 성능·확장 감각을 보는 단골. 국내 백엔드에서 Redis가 사실상 표준 캐시/세션 저장소라 깊게 묻는다.
함정형 단골: ① Redis는 싱글스레드라 느리다? → 인메모리+이벤트 루프로 빠름(단 O(N) 명령 주의) ② Redis 분산락이면 100% 안전? → Redlock 한계.
1. 왜 캐시인가·전략 (★★ 단골)
실제 질문: "캐시 전략(Look-aside/Write-through/Write-back)을 설명하라." · "캐시 무효화는 왜 어려운가요?"
DB·복잡 계산·외부 API는 느리고 비싸다 → 자주 읽고 잘 안 바뀌는 데이터를 메모리(Redis)에 복사 → 지연↓·DB 부하↓. 핵심 트레이드오프 = 속도 vs 일관성(캐시는 원본과 어긋날 수 있다).
읽기 — Cache-Aside (Look-Aside·가장 흔함)
read(key):
v = cache.get(key)
if v == null: # 미스
v = db.query(key); cache.set(key, v, TTL)
return v
쓰기 전략
| 전략 | 동작 | 특징 |
|---|---|---|
| Write-Through | 캐시·DB 동시 갱신 | 일관성↑·쓰기 지연↑ |
| Write-Back | 캐시 먼저·DB 비동기 | 빠름·장애 시 유실 |
| Write-Around | DB만·캐시는 무효화 | 안 읽힐 데이터로 안 더럽힘 |
꼬리질문: "캐시 무효화가 왜 어려운가?" → 원본 변경을 언제·어떻게 캐시에 반영할지(stale·동시성). / "쓰기 시 갱신 vs 삭제?" → 삭제가 보통 안전(동시성으로 잘못된 값 캐시 방지).
2. 캐시 무효화·일관성 (★★ 단골·"2대 난제")
"There are only two hard things in CS: cache invalidation and naming things."
- TTL(만료): 가장 단순(약간 stale 허용).
- 쓰기 시 캐시 삭제(invalidate)가 보통 안전(갱신은 경쟁 조건으로 옛 값을 다시 쓸 수 있음 → 다음 읽기에 재적재).
- CDC 기반: DB 변경 로그(binlog)를 구독해 캐시 무효화(정합성↑).
깊이 — Cache-Aside 동시성: "DB 갱신 ↔ 캐시 삭제" 순서·동시 읽기가 엮이면 옛 값이 다시 캐시될 틈 → 삭제(갱신 아님)·짧은 TTL·버전으로 완화.
꼬리질문: "캐시-DB 강한 일관성?" → 어렵다 → TTL·무효화·CDC·결과적 일관성 수용. / "캐시 워밍?" → 배포·재시작 후 미리 적재(콜드 스타트 폭주 방지).
3. 캐시 스탬피드(Thundering Herd) (★★ 단골·심화)
실제 질문: "캐시 스탬피드 현상을 설명하고 해결책을 말하라." (매일메일·화해 기술블로그)
인기 키 TTL 만료 순간 수많은 요청이 동시에 캐시 미스 → DB로 몰려 죽음. 해결:
- 분산 락/single-flight: 첫 미스만 락 잡고 DB 조회·채움, 나머지는 대기 후 캐시 읽기.
- TTL 지터(jitter): 만료 시각에 랜덤 오프셋 → 동시 만료 분산.
- PER(Probabilistic Early Recomputation): 만료 전에 확률적으로 미리 갱신(
xfetch가중치). - 백그라운드 갱신/캐시 워밍: 스케줄러가 선제 갱신.
꼬리질문: "락 방식 단점?" → 나머지 요청의 대기 지연. / "PER의 장점?" → 만료 직전 일부만 미리 갱신해 동시 미스 방지.
함정: ❌ "TTL만 걸면 일관성·스탬피드 해결" → 동시 만료 폭주 미고려.
4. eviction·미스·히트율 (★ 심화)
실제 질문: "maxmemory 도달 시 Redis는 어떻게 동작하나요?"
maxmemory 도달 시 **maxmemory-policy**로 무엇을 버릴지:
| 정책 | 동작 |
|---|---|
noeviction | 기본 — 안 버리고 쓰기 에러 |
allkeys-lru/lfu | 전체 중 오래/적게 쓴 키 |
volatile-lru/lfu/ttl | TTL 있는 키 중에서만 |
Redis LRU/LFU는 정확이 아니라 샘플링 근사(
maxmemory-samples기본 5). 미스 종류 = Cold(최초)·Capacity(eviction)·무효화 미스(Conflict miss는 CPU set-associative 캐시 개념이라 Redis엔 무관). 히트율 = hits/(hits+misses)(INFO stats).
5. Redis 자료구조 (★ 단골)
실제 질문: "Redis의 자료구조와 활용 사례를 설명하라."
| 타입 | 활용 |
|---|---|
| String | 캐시·카운터(INCR)·분산 락(SET NX EX) |
| Hash | 객체(필드-값)·세션 |
| List | 큐·최근 N개 |
| Set | 중복 제거·집합 연산 |
| Sorted Set(ZSet) | 랭킹/리더보드(score 정렬 O(log n)) |
| Stream | 이벤트 로그·소비자 그룹 |
| Bitmap·HyperLogLog | 출석·대규모 고유 카운트(근사) |
꼬리질문: "실시간 랭킹은?" → ZSet(score로 자동 정렬). / "좋아요 수 동시성?" → INCR(원자적).
6. Redis 특성·고가용성 (★ 단골)
실제 질문: "Redis는 왜 빠른가요? 싱글 스레드인데 괜찮나요?" · "영속성(RDB/AOF)은?"
- 명령 실행 단일 스레드(네트워크 I/O는 멀티플렉싱) → 원자적 명령·경쟁 없음·락 불필요. ⚠️ 느린 명령(
KEYS *·큰 O(N))이 전체를 블로킹 →SCAN·작은 단위. - 빠른 이유: 인메모리·단일 스레드(컨텍스트 스위칭·락 없음)·효율적 자료구조·I/O 멀티플렉싱.
- 영속성: RDB(시점 스냅샷·빠른 복구·일부 유실) vs AOF(쓰기 명령 로그·유실 적음·파일 큼). 함께도.
- 고가용성: 복제(replica)·Sentinel(자동 페일오버) vs Cluster(샤딩·수평 확장·16384 슬롯).
꼬리질문: "KEYS *가 위험한 이유?" → 단일 스레드를 블로킹(전체 키 스캔) → SCAN. / "RDB vs AOF 선택?" → 복구 속도(RDB) vs 유실 최소(AOF).
함정: ❌ "싱글 스레드라 느리다" → 인메모리·락 없음으로 빠름(O(N) 명령만 주의).
7. 분산 락 — Redis (★★ 심화·재고 동시성)
실제 질문: "재고 100개에 200 요청이 동시에 오면 어떻게 처리하나요?" · "Lettuce vs Redisson 분산 락?" · "Redis 분산 락이 안전한가요?"(Redlock)
- 기본:
SET key val NX EX 10(원자적 획득+만료). ⚠️ 만료 전 작업 미완·소유권 문제. - Lettuce: 스핀락(폴링) → Redis 부하↑. Redisson: Pub/Sub 기반 재시도 + lease(타임아웃) + watchdog(작업이 lease보다 길면 자동 연장) → 권장.
- Redlock(여러 노드 과반): 단일 Redis 장애 대비. 단 Martin Kleppmann의 안전성 논쟁 — GC 일시정지·네트워크 분할 시 두 노드가 동시에 락을 점유할 수 있어 fencing token(단조 증가 토큰으로 순서 보장)이 필요.
깊이 — 재고 동시성: DB 비관락(SELECT FOR UPDATE)·낙관락(version)·Redis 분산락·원자적 DECR/UPDATE … WHERE stock>0. 고경합엔 분산락 또는 원자 연산.
꼬리질문: "Redisson 락이 lease보다 길면?" → watchdog이 자동 연장. / "분산락도 100% 안전?" → 아니다(GC pause·분할) → fencing token. / "핫키?" → 특정 키 집중 → 로컬 캐시·복제.
함정: ❌ "Redis 분산락이면 100% 안전" → Redlock도 한계(fencing token).
8. Redis vs Memcached·ElasticSearch (★ 기출 보강·2026-07)
실제 질문: "Redis와 Memcached의 차이는?" · "ElasticSearch를 왜 쓰나요? RDBMS 인덱스와 ES 인덱스의 차이는?" · "ES 키워드 검색과 RDBMS의 LIKE 검색의 차이는?" (ksundong·gyoogle)
Redis vs Memcached — 둘 다 인메모리 KV 캐시지만:
| Redis | Memcached | |
|---|---|---|
| 자료구조 | String·Hash·List·Set·ZSet·Stream·Bitmap·HLL | 단순 key-value(문자열)만 |
| 스레드 | 명령 단일 스레드(6.0+ I/O만 멀티) | 멀티스레드(멀티코어 순수 처리량↑) |
| 영속성 | RDB·AOF | 없음(순수 캐시·재시작 시 소멸) |
| 고가용성/확장 | 복제·Sentinel·Cluster(16384 슬롯) | 서버 복제 없음·클라이언트 샤딩(consistent hashing) |
| eviction·메모리 | maxmemory-policy(LRU/LFU 근사)·jemalloc | LRU·slab allocator(단편화↓·큰 값 비효율) |
| 기타 | pub/sub·Lua·트랜잭션·분산락·TTL/키 | 단순·가벼움 |
언제: 단순 KV + 멀티코어 처리량만 필요 → Memcached, 자료구조·영속성·pub/sub·랭킹·분산락 → Redis(국내 실무는 Redis가 사실상 표준). 꼬리질문: "Memcached가 유리한 경우?" → 값이 단순 문자열이고 순수 look-aside 캐시로 멀티코어를 꽉 쓰고 싶을 때. "Redis도 멀티스레드?" → 6.0+는 네트워크 I/O만 멀티, 명령 실행은 단일(원자성 유지).
ElasticSearch 인덱스 vs RDBMS 인덱스 — 목적·자료구조가 다르다:
- RDBMS(B+Tree): 정렬된 키 → 정확 매칭·범위·정렬.
LIKE '%word%'(선두 와일드카드)는 인덱스를 못 타 풀스캔. - ES(역색인, inverted index): 용어(term) → 문서 목록 매핑. 문서를 analyzer(tokenizer + 소문자화·불용어·형태소 filter)로 토큰화해 색인 → 전문검색(full-text) 에 최적.
- 키워드 검색 vs LIKE: ES는 토큰 단위 매칭 + 관련도 랭킹(BM25) + fuzzy(오타)·형태소 분석 → 관련도 순 정렬.
LIKE는 부분 문자열만·랭킹 없음·대소문자/형태소 무시·대량이면 느림. - 언제 ES: 전문검색·로그 분석·대규모 텍스트 집계. 단 near-real-time(refresh interval 후 검색 가능)·최종 일관성이라 트랜잭션·강한 정합성은 RDBMS가 진실의 원천, ES는 검색용 read model로 CDC/색인 파이프라인으로 동기화.
함정: ❌ "ES가 DB를 대체한다" → 검색·집계 특화, 트랜잭션·정합성은 RDBMS. ❌ "LIKE도 인덱스 타니 ES 불필요" → 선두 와일드카드·형태소·랭킹은 LIKE로 불가.
(출처: Redis docs — data types·persistence·cluster·Memcached wiki·Elastic — inverted index·analysis·BM25 교차검증. 기출 프레이밍: docs/01-ksundong.)
흔한 오답·함정 정리
- Redis는 싱글 스레드라 느리다 → 인메모리·락 없음으로 빠름(O(N) 명령 주의).
- TTL만 걸면 일관성·스탬피드 해결 → 동시 만료 폭주 미고려.
- Redis 분산락이면 100% 안전 → Redlock 한계(fencing token).
KEYS *로 키 조회 → 블로킹 →SCAN.- 쓰기 시 캐시 갱신이 안전 → 삭제가 보통 안전(동시성).
한국 면접 단골 Q&A (답변 골격)
| 질문 | 핵심 답 |
|---|---|
| 캐시 전략 | cache-aside·write-through/back/around |
| 캐시 무효화·일관성 | TTL·삭제·CDC·결과적 일관성 |
| 캐시 스탬피드 | 인기 키 동시 미스→락·PER·TTL 지터 |
| eviction | maxmemory-policy·LRU/LFU 근사·noeviction 기본 |
| Redis 자료구조 | String/Hash/List/Set/ZSet·랭킹=ZSet |
| Redis 싱글 스레드 | 원자적·KEYS * 블로킹 주의 |
| 왜 빠른가 | 인메모리·락 없음·멀티플렉싱 |
| 영속성 | RDB 스냅샷 vs AOF 로그 |
| 분산 락 | SET NX EX·Redisson watchdog·Redlock/fencing |
| Cluster vs Sentinel | 샤딩 vs 페일오버 |
꼬리질문 대비 (상 난이도)
- "캐시 죽으면?" → DB 폴백·스탬피드 폭주 주의·Sentinel/Cluster.
- "분산락 만료됐는데 작업 미완?" → 다른 노드가 같은 락 → fencing token으로 순서 보장.
- "느린 응답이 Redis?" → 단일 스레드라
KEYS *·빅키 블로킹 →SCAN·빅키 분할. - "핫키/빅키?" → 트래픽 집중·큰 키 → 로컬 캐시·분할.
- "재고 과매도?" → 분산락·원자
DECR·UPDATE WHERE stock>0.
한 줄 요약 — 캐시는 속도↔일관성. 읽기 cache-aside·쓰기 write-through/back. 무효화는 TTL·삭제·CDC(2대 난제). 스탬피드는 락/PER/TTL 지터. eviction은 maxmemory-policy(LRU/LFU 근사·noeviction 기본). Redis는 명령 단일 스레드(빠름·
KEYS *블로킹)·RDB/AOF·ZSet 랭킹·분산 락(Redisson watchdog·Redlock 한계→fencing token)·Cluster(샤딩)/Sentinel(페일오버).
(출처 — 한국 면접 기출·교차검증 2026-06: gyoogle — Redis·매일메일 — 캐시 스탬피드·화해 기술블로그 — PER·velog — Redisson 분산 락 · Redis 공식 — eviction·persistence·distributed locks·Kleppmann — Redlock 비판 교차검증.)