캐시 2
- 캐시의 핵심 원리
- 시간적 지역성과 공간적 지역성의 개념
- 캐시 히트(Cache Hit), 캐시 미스(cache Miss)의 차이
- 캐시 적중률(Cache Ratio)의 계산 방식과 의미
- 캐시 성능이 시스템에 얼마나 효율적인가?
1. 캐시의 핵심 원리 개요
캐시가 왜 이렇게 빠른 속도를 낼 수 있는가?? - 내부 원리 알아보기
캐시의 성능을 결정하는 핵심 개념, 4가지
- 시간적 지역성(Temporal Locality)
- 공간적 지역성(Spatial Locality)
- 캐시 히트(Cache Hit), 캐시 미스(Cache Miss)
- 캐시 적중률(Cache Ratio)
이 네 가지 원리는 캐시가 데이터를 효율적으로 저장하고 재사용하는 근본적 이유를 설명한다.
2. 시간적 지역성(Temporal Locality)
1) 개념
시간적 지역성이란, 최근에 사용한 데이터는 가까운 미래에도 다시 사용될 가능성이 높다 - 라는 원리임
사용자가 쇼핑몰에서 노트북을 검색했다면, 곧이어 같은 상품을 여러 번 다시 조회하거나 관련 정보를 볼 확률이 높다.
즉, 최근에 접근된 데이터를 캐시에 보관한다면 다시 요청할 때 즉시 응답할 수 있다.
시간적 지역성의 경우 대부분의 캐시 시스템이 TTL(Time To Live, 유효 기간) 개념을 사용하는 이유가 되기도 한다.
최근 접근된 데이터는 일정 시간 유지되어 반복 요청에 대해 빠르게 대응할 수 있다.
2) 예시
import java.util.HashMap;
import java.util.Map;
public class TemporalLocalityWithTTLExample {
static class CacheItem {
String value;
long expireAt; // 만료시각, 밀리초 단위라 long
CacheItem(String value, long ttlMillies) {
this.value = value;
this.expireAt = System.currentTimeMillis() + ttlMillies;
}
boolean expired() { // 만료됨
// 현재 시간이 expiredAt보다 크면, 만료되었음을 의미함, 지정한 ttlMilles를 지났기 때문
return System.currentTimeMillis() > expireAt;
}
}
// 캐시 필드
private static final Map<String, CacheItem> cache = new HashMap<>();
// 캐시에서 데이터를 조회하는 메서드
public static String getData(String key) {
CacheItem item = cache.get(key); // key값 찾고
// 캐시에 item이 존재하며, 만료되지 않았다면
if(item != null && !item.expired()) {
System.out.println("[Cache Hit] 캐시에서 데이터를 반환합니다.");
return item.value; // 캐시에서 value 리턴
}
// 필터링에 걸리지 않았다면 캐시에 데이터가 없다는 것을 의미함, DB에서 조회
System.out.println("[Cache Miss] 원본 데이터를 조회합니다.");
String data = key + "상품 정보"; // 이게 원본 데이터라고 가정함
cache.put(key, new CacheItem(data, 3000)); // 캐시에 key와 item을 적재함
return data;
}
public static void main(String[] args) {
try {
System.out.println(getData("노트북")); // 첫번째 요청
Thread.sleep(1000);
System.out.println(getData("노트북")); // 두번째 요청, 1초 후
Thread.sleep(4000);
System.out.println(getData("노트북")); // 세번째 요청, 4초 후
} catch(InterruptedException e) {
System.out.printf("예기치 못한 무언가가 발생, {}", e);
}
}
}
결과
[Cache Miss] 원본 데이터를 조회합니다.
노트북상품 정보
[Cache Hit] 캐시에서 데이터를 반환합니다.
노트북상품 정보
[Cache Miss] 원본 데이터를 조회합니다.
노트북상품 정보
* 같은 키워드를 짧은 시간 내에 반복 호출하면 시간적 지역성이 작동하여 빠르게 동작한다.
3. 공간적 지역성(Spatial Locality)
1) 개념 설명
공간적 지역성은, 어떤 데이터가 사용되면 그 주변(인접) 데이터도 곧 사용될 가능성이 높다 - 라는 원리임
사용자가 '노트북' 정보를 조회했다면, 비슷한 시점에 '노트북 케이스', '마우스' 와 같은 관련 상품을 볼 가능성이 높다.
이러한 원리를 이용하면 캐시가 하나의 데이터뿐만 아니라 인접한 데이터까지 함께 저장하여, 이후 요청시 빠르게 제공할 수 있다.
2) 예시
이거 좀 이해하기 어려웠음
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SpatialLocalityImprovedExample {
private static final Map<String, List<String>> database = new HashMap<>(); // 여기가 DB라고 가정
private static final Map<String, List<String>> cache = new HashMap<>(); // 여기가 Cache라고 가정
static {
database.put("노트북", Arrays.asList("노트북", "마우스", "키보드", "노트북 가방"));
database.put("마우스", Arrays.asList("마우스", "마우스 패드", "키보드"));
}
public static List<String> getRelatedProducts(String keyword) {
// cache에 key가 있다면, DB 조회 과정을 스킵한다
if(cache.containsKey(keyword)) {
System.out.println("[Cache Hit] 캐시에서 연관 데이터를 반환합니다.");
return cache.get(keyword); // 리턴을 한번 함
}
// 이후는 cache에 key가 없는 상태임
// DB를 조회하는 과정
System.out.println("[Cache Miss] DB에서 연관 데이터를 조회합니다.");
List<String> data = database.getOrDefault(keyword, Collections.emptyList());
// 핵심 포인트 : 인접 데이터까지 함께 캐싱함
for(int i=0; i<data.size(); i++) {
String related = data.get(i); // 키워드 가져옴
// cache에 data key가 없고, DB에 key가 있다면
if(!cache.containsKey(related) && database.containsKey(related)) {
cache.put(related, database.get(related));
}
}
// for문을 빠져나와 cache에 put된 상태
// cache에 key를 넣음
cache.put(keyword, data);
return data;
}
public static void main(String[] args) {
System.out.println(getRelatedProducts("노트북")); // miss 발생 - > 주변 데이터도 캐싱함
System.out.println(getRelatedProducts("마우스")); // 이미 인접 캐싱되여 hit함
}
}
결과
[Cache Miss] DB에서 연관 데이터를 조회합니다.
[노트북, 마우스, 키보드, 노트북 가방]
[Cache Hit] 캐시에서 연관 데이터를 반환합니다.
[마우스, 마우스 패드, 키보드]
* 인접한 데이터들을 함께 캐싱하여, 사용자의 다음 행동을 예측한 빠른 응답이 가능함
4. 캐시 히트(Cache Hit), 캐시 미스(Cache Miss)
1) 개념 설명
- 캐시 히트 : 요청한 데이터가 캐시에 존재하여 즉시 응답이 가능한 경우
- 캐시 미스 : 요청한 데이터가 캐시에 없어 원본 데이터 소스(DB 등..)를 다시 조회해야 하는 경우
캐시 히트는 빠른 응답을 제공하지만, 캐시 미스는 추가 연산(조회, 저장 등 로직)을 필요로 함
2) 시나리오
- 첫번째 요청 - > 캐시 미스 발생 - > DB에서 조회 후 캐시에 저장함
- 두번째 요청 - > 캐시 히트 발생 - > 캐시에서 즉시 응답
결과적으로 캐시 히트가 많을수록 시스템 성능은 향상된다.
5. 캐시 적중률(Cache Hit Ratio)
개념
캐시 적중률은 전체 요청 중 캐시 히트가 발생한 비율임
Cache Hit Ratio = (Cache Hit 횟수 / 전체 요청 횟수) * 100%
전체 요청 수가 100, 캐시 히트 수가 80, 캐시 미스 수가 20이면 캐시 적중률은 80 / 100 * 100, 80%이다
* 캐시 적중률이 높을수록 시스템은 더 빠르고 효율적으로 동작함
팁
* 적중률 80 ~ 90% 이상을 유지하는 것이 일반적이고, 이상적이다.
* 적중률이 낮다면 TTL이 너무 짧거나, 캐시할 데이터 선정이 잘못되었을 가능성이 높음
* 데이터 변경이 잦은 경우, 오히려 캐시 오버헤드가 생길 수 있으므로 주의해야함
* 실제 시스템에서는 Prometheus, Grafana, Elastic Stack 등을 활용해서 캐시 적중률을 모니터링 한다고 함
정리
| 핵심 개념 | 설명 |
| 시간적 지역성 | 최근 사용한 데이터는 곧 다시 사용될 가능성이 높음 |
| 공간적 지역성 | 인접한 데이터도 함께 사용될 가능성이 높음 |
| 캐시 히트 | 요청한 데이터가 캐시에 존재하여, 즉시 응답함 |
| 캐시 미스 | 캐시에 없어서 DB 등에서 새로 조회해야 하는 상황임 |
| 캐시 적중률 | 전체 요청 중 캐시 히트의 비율(성능 지표) |
'Spring Boot > Cache' 카테고리의 다른 글
| 캐시 아키텍처와 종류 : 주요 캐시 솔루션 비교 (0) | 2026.01.02 |
|---|---|
| 캐시 아키텍처와 종류 : 캐시 계층 구조 (0) | 2025.12.31 |
| 캐시의 기본 개념과 필요성 : 캐시 적용 고려사항 (0) | 2025.12.31 |
| 캐시의 기본 개념과 필요성 : 대용량 트래픽에서 캐시의 역할 (0) | 2025.12.21 |
| 캐시의 기본 개념과 필요성 : 캐시의 정의와 목적 (0) | 2025.12.19 |