값비싼 연산 결과나 자주 읽는 데이터를 DB보다 빠른 메모리 저장소에 두고, 읽을 때 캐시를 먼저 보는 전략. 응답 속도를 높이고 DB 부하를 줄이며, 캐시 계층만 따로 확장할 수도 있다.
읽기 흐름
- 요청이 오면 캐시에 값이 있는지 본다
- 있으면 바로 돌려준다(캐시 히트, Cache Hit)
- 없으면 DB에서 읽어 캐시에 넣고 돌려준다(캐시 미스, Cache Miss)
애플리케이션이 이 흐름을 직접 짜면 cache-aside(지연 로딩), 캐시 라이브러리나 계층이 DB 조회까지 대신해 주면 read-through라고 구분한다. 흐름은 같고 책임이 누구에게 있느냐가 다르다.
설계할 때 정할 것
- 만료(Time To Live, TTL): 너무 짧으면 DB를 자주 치고, 너무 길면 옛 데이터를 보여 준다
- 일관성: DB를 고친 뒤 캐시를 지우거나 갱신하는 순서를 정한다. 완벽한 동기화는 어렵다
- 휘발성: 캐시는 재시작하면 사라진다. 중요한 데이터는 영속 저장소에 둔다
- 방출 정책(Eviction Policy): 공간이 차면 무엇을 버릴지. 가장 오래 안 쓴 것(Least Recently Used, LRU), 가장 적게 쓴 것(Least Frequently Used, LFU) 등(LRU 캐시와 캐시 계층 비교)
- 크기와 SPOF(Single Point of Failure): 너무 작으면 자주 밀려나고 너무 크면 낭비다. 캐시 서버 하나에 의존하지 않게 분산한다
캐시 서버로는 Redis (인메모리 저장소)가 대표적이다. 같은 원리가 계층마다 반복된다. JPA의 1차 캐시, 브라우저의 HTTP 캐시, 프런트엔드의 TanStack Query·Next.js 캐시 계층. 전체 흐름은 사용자 수에 따른 규모 확장.
출처: 『가상 면접 사례로 배우는 대규모 시스템 설계 기초』 알렉스 쉬 (원서 System Design Interview – An Insider's Guide) 1장