
안녕하세요, 이력서 기반 면접 준비를 도와드리는 QueryDaily 팀입니다.
혹시 이런 경험 있으신가요?
"Redis 캐시 사용 경험 있으시네요. 캐시 전략은 어떤 걸 사용하셨나요?"
"음... 그냥 자주 조회하는 데이터를 캐시에 넣었는데요..."
캐시를 '사용'한 경험은 있지만, '왜 그 전략을 선택했는지', '다른 전략과의 차이점은 무엇인지' 설명하라고 하면 막막해지는 상황. 면접관은 바로 이 지점을 파고듭니다.
오늘은 면접에서 자주 등장하는 캐시 전략(Caching Strategy) 에 대해 깊이 있게 알아보겠습니다.
캐시는 자주 사용되는 데이터를 빠르게 접근할 수 있는 임시 저장소에 보관하는 기술입니다.
[클라이언트] → [애플리케이션 서버] → [캐시(Redis 등)] → [데이터베이스]
면접 팁: "캐시를 왜 사용하셨나요?"라는 질문에는 단순히 "빨라서요"가 아닌, 구체적인 수치와 상황을 들어 설명하세요. "상품 목록 조회 API의 평균 응답 시간이 500ms였는데, 캐시 적용 후 50ms로 개선되었습니다" 처럼요.
캐시 전략은 크게 읽기 전략과 쓰기 전략으로 나눌 수 있습니다.

가장 널리 사용되는 패턴으로, 애플리케이션이 직접 캐시를 관리합니다.
public Product getProduct(Long productId) {
// 1. 캐시에서 먼저 조회
Product cached = cache.get("product:" + productId);
if (cached != null) {
return cached; // Cache Hit!
}
// 2. Cache Miss - DB에서 조회
Product product = productRepository.findById(productId);
// 3. 캐시에 저장
cache.put("product:" + productId, product, Duration.ofMinutes(30));
return product;
}
동작 방식:
1. 캐시에서 데이터 조회 시도
2. Cache Hit → 캐시 데이터 반환
3. Cache Miss → DB 조회 → 캐시에 저장 → 반환
장점:
단점:
Cache-Aside와 비슷하지만, 캐시 라이브러리가 DB 조회를 담당합니다.
// 캐시 설정 시 Loader 정의
Cache<Long, Product> cache = CacheBuilder.newBuilder()
.expireAfterWrite(30, TimeUnit.MINUTES)
.build(new CacheLoader<Long, Product>() {
@Override
public Product load(Long productId) {
// Cache Miss 시 자동으로 호출됨
return productRepository.findById(productId);
}
});
// 사용 - 캐시가 알아서 처리
public Product getProduct(Long productId) {
return cache.get(productId); // Hit이든 Miss든 동일한 코드
}
Cache-Aside vs Read-Through:
| 구분 | Cache-Aside | Read-Through |
|---|---|---|
| DB 조회 주체 | 애플리케이션 | 캐시 라이브러리 |
| 코드 복잡도 | 조건문 필요 | 단순함 |
| 유연성 | 높음 | 낮음 (Loader에 의존) |
데이터 쓰기 시 캐시와 DB에 동시에 저장하는 전략입니다.
public void updateProduct(Product product) {
// 1. DB에 저장
productRepository.save(product);
// 2. 캐시에도 저장 (동기)
cache.put("product:" + product.getId(), product);
}
장점:
단점:
캐시에만 먼저 쓰고, DB에는 비동기로 나중에 저장하는 전략입니다.
public void updateProduct(Product product) {
// 1. 캐시에만 먼저 저장 (빠름!)
cache.put("product:" + product.getId(), product);
// 2. 비동기로 DB 저장 (배치 처리)
writeQueue.add(product); // 별도 스레드가 주기적으로 DB에 flush
}
장점:
단점:
❌ 주의: Write-Behind는 데이터 유실 가능성 때문에 결제, 주문 등 중요 데이터에는 사용하면 안 됩니다.
쓰기는 DB에만, 캐시는 읽기 시에만 갱신하는 전략입니다.
public void updateProduct(Product product) {
// DB에만 저장
productRepository.save(product);
// 캐시는 삭제 (다음 읽기 시 갱신되도록)
cache.delete("product:" + product.getId());
}
장점:
단점:

DB와 캐시의 데이터가 달라지는 상황입니다.
시간순서:
1. [서버 A] 캐시 삭제
2. [서버 B] 캐시 조회 - Miss! - DB 조회 - 옛날 데이터를 캐시에 저장
3. [서버 A] DB 업데이트
→ 결과: 캐시에는 옛날 데이터, DB에는 새 데이터 😱
해결 방법:
캐시가 만료되는 순간, 수많은 요청이 동시에 DB로 몰리는 현상입니다.
[캐시 만료] → 1000개 요청 동시에 Cache Miss → DB에 1000개 쿼리 폭탄 💥
해결 방법:
// 1. 뮤텍스 락 사용
public Product getProductWithLock(Long productId) {
Product cached = cache.get("product:" + productId);
if (cached != null) return cached;
// 락 획득 시도
if (lock.tryLock("product_lock:" + productId)) {
try {
// 더블 체크
cached = cache.get("product:" + productId);
if (cached != null) return cached;
Product product = productRepository.findById(productId);
cache.put("product:" + productId, product);
return product;
} finally {
lock.unlock("product_lock:" + productId);
}
}
// 락 획득 실패 시 잠시 대기 후 재시도
Thread.sleep(50);
return getProductWithLock(productId);
}
// 2. 확률적 조기 갱신 (Probabilistic Early Expiration)
// TTL 만료 전에 일정 확률로 미리 갱신
if (remainingTTL < threshold && Math.random() < 0.1) {
// 10% 확률로 미리 갱신
refreshCache(productId);
}
특정 키에 트래픽이 집중되어 단일 캐시 노드에 부하가 몰리는 현상입니다.
해결 방법:
product:123:replica1, product:123:replica2 등으로 분산
핵심 포인트: DB 조회 주체가 다릅니다.
Cache-Aside는 애플리케이션이, Read-Through는 캐시 라이브러리가 DB를 조회합니다.
답변 포인트:
- TTL 기반: 일정 시간 후 자동 만료
- 이벤트 기반: 데이터 변경 시 즉시 삭제
- 버전 기반: 데이터 버전 비교로 유효성 판단
답변 포인트:
- 일관성 vs 성능
- 메모리 비용 vs 응답 속도
- 복잡도 증가 vs 확장성
핵심: 데이터 유실이 치명적인 경우 (결제, 주문, 재고 등). 캐시 장애 시 미처 DB에 저장되지 않은 데이터가 사라질 수 있습니다.
| 전략 | 읽기 성능 | 쓰기 성능 | 일관성 | 적합한 상황 |
|---|---|---|---|---|
| Cache-Aside | ⭐⭐⭐ | - | 보통 | 범용적으로 사용 |
| Read-Through | ⭐⭐⭐ | - | 보통 | 캐시 라이브러리 활용 시 |
| Write-Through | ⭐⭐⭐ | ⭐⭐ | 높음 | 일관성이 중요한 경우 |
| Write-Behind | ⭐⭐⭐ | ⭐⭐⭐ | 낮음 | 쓰기 성능이 중요한 경우 |
| Write-Around | ⭐⭐ | ⭐⭐⭐ | 보통 | 자주 읽히지 않는 데이터 |
캐시 전략은 정답이 없습니다. 서비스의 특성, 데이터의 성격, 허용 가능한 불일치 시간 등을 종합적으로 고려해서 선택해야 합니다.
면접에서도 "이 전략이 무조건 좋다"가 아닌, "우리 상황에서는 이런 이유로 이 전략을 선택했다" 라고 말할 수 있어야 합니다.
오늘 살펴본 것처럼, 캐시는 단순히 "데이터를 저장하는 곳"이 아닙니다. 어떤 전략을 선택하느냐에 따라 시스템의 성능, 일관성, 복잡도가 크게 달라집니다. 이력서에 "Redis 캐시 적용"이라고 한 줄 적었다면, 그 뒤에 숨겨진 수많은 결정들에 대해 설명할 준비가 되어 있어야 합니다.
QueryDaily와 함께 여러분의 이력서에서 파생될 수 있는 꼬리 질문들을 미리 연습해 보세요.
#캐시 #Cache #Redis #백엔드면접 #QueryDaily