- Spring Boot Actuator를 사용하여 애플리케이션의 캐시 상태를 실시간으로 모니터링 하는법
- 캐시 관련 엔드포인트(/actuator/caches, /actuator/metrics/cache.*) 의 활용법??
- Micrometer를 이용해 캐시 통계를 수집하고 분석하는법
- 커스텀 지표(Metrics)를 정의하여 비즈니스 맞춤형 모니터링 구성하기
- 실무에서 캐시 문제를 조기에 탐지하고 효율적으로 관리할 수 있는 법
Spring Boot Actuator를 활용한 모니터링
Spring Boot Actuator는 운영 환경에서의 시스템 상태를 실시간으로 관찰할 수 있도록 도와주는 강력한 모니터링 도구임
Actuator는 캐시의 Hit/Miss 비율, 캐시 크기, 만료 정책 등의 캐시 통계 정보까지 노출할 수 있음
1. Actuator의 개념
Actuator는 Micrometer를 기반으로 작동하며, 다양한 모니터링 툴과 연동할 수 있음
이를 통해 캐시 동작을 포함한 애플리케이션의 내부 상태를 시각화할 수 있음
2. Actuator 활성화
Spring Boot 프로젝트에서 Actuator를 사용하려면 의존성을 추가해야함
build.gradle
// spring actuator
implementation 'org.springframework.boot:spring-boot-starter-actuator'
// 선택 : Prometheus 연동 시
implementation 'io.micrometer:micrometer-registry-prometheus'
이후 application.yml에 캐시 관련 엔드포인트를 활성화함
application.yml
spring:
application:
name: actuatorTest
management:
endpoints:
web:
exposure:
include: health, info, metrics, caches
endpoint:
caches:
enabled: true # 곧 사용하지 않는 프로퍼티임
metrics:
enable:
cache: true # 자동입력 안됨
include: caches를 추가해줘야 /actuator/caches 엔드포인트가 노출된다고 함
캐시 관련 엔드포인트
Spring Boot Actuator는 캐시와 관련된 엔드포인트들을 제공하고 있음
| 엔드포인트 | 설명 |
| /actuator/caches | 현재 등록된 모든 캐시 이름과 상태 정보를 조회함 |
| /actuator/caches/{cacheName} | 특정 캐시의 내부 상태를 확인함 |
| /actuator/metrics/cache.gets | 캐시 Hit/Miss 통계를 조회함 |
| /actuator/metrics/cache.puts | 캐시 저장(Put) 이벤트 통계를 조회함 |
| /actuator/metrics/cache.evictions | 캐시 항목 제거(Eviction) 횟수를 조회함 |
1. /actuator/caches 예시 응답
json 형태임
http://localhost:8080/actuator/caches
{
"cacheManagers": {
"caffeineCacheManager": {
"caches": {
"productCache": {
"target": "com.github.benmanes.caffeine.cache.BoundedLocalCache$BoundedLocalManualCache"
},
"userCache": {
"target": "com.github.benmanes.caffeine.cache.BoundedLocalCache$BoundedLocalManualCache"
}
}
}
}
}
이 결과는 현재 등록된 캐시(userCache, productCache)의 이름과 타입을 보여줌
캐시 통계 수집
Spring Boot Actuator는 Micrometer랑 결합되어 캐시 관련 통계를 자동으로 수집하게 해줌
build.gradle
// spring actuator
implementation 'org.springframework.boot:spring-boot-starter-actuator'
// 선택 : Prometheus 연동 시
implementation 'io.micrometer:micrometer-registry-prometheus'
// cache
implementation 'org.springframework.boot:spring-boot-starter-cache'
// caffeine
implementation 'com.github.ben-manes.caffeine:caffeine'
1. Caffeine Cache에서 통계 활성화
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
@Configuration
@EnableCaching
public class CacheConfig {
public CacheManager caffeineCacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("userCache, productCache");
cacheManager.setCaffeine(Caffeine.newBuilder()
.maximumSize(1000)
.recordStats()
.expireAfterWrite(10, TimeUnit.MINUTES));
return cacheManager;
}
}
recordStats()를 활성화하면 Hit / Miss, Eviction 등 캐시 관련 통계가 자동으로 수집됨
2. 캐시 통계 조회 예시
/actuator/metrics/cache.gets 요청시 결과를 얻을 수 있다고 함
물론 json 형태
{
"name": "cache.gets",
"description": "The number of times cache lookup methods have returned a cached (hit) or uncached (newly loaded or null) value (miss).",
"measurements": [
{
"statistic": "COUNT",
"value": 0.0
}
],
"availableTags": [
{
"tag": "result",
"values": [
"hit",
"miss"
]
},
{
"tag": "cache.manager",
"values": [
"caffeine"
]
},
{
"tag": "cache",
"values": [
"userCache, productCache"
]
},
{
"tag": "name",
"values": [
"userCache, productCache"
]
}
]
}
result 부분에서
hit : 캐시에서 데이터를 성공적으로 가져온 횟수
miss : 캐시에 데이터가 없어 DB등 원본 데이터 소스에서 조회한 횟수
캐시 상태 모니터링 워크플로우
이러한 구조를 통해 실시간 캐시 상태 관찰 및 트렌드 분석이 가능함
커스텀 지표 구성
Actuator가 제공하는 기본 지표들 외에도, 비즈니스 로직에 맞춰 커스텀 캐시 지표를 추가할 수도 있음
import com.github.benmanes.caffeine.cache.Cache;
import io.micrometer.core.instrument.MeterRegistry;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class CustomCacheMetrics {
private final CaffeineCacheManager cacheManager;
private final MeterRegistry registry; // micrometer import
@PostConstruct
public void registerCustomMetrics() {
cacheManager.getCacheNames().forEach(cacheName -> {
CaffeineCache cache = (CaffeineCache) cacheManager.getCache(cacheName);
Cache<Object, Object> nativeCache = cache.getNativeCache();
registry.gauge("custom.cache.size", nativeCache.estimatedSize()); // size
registry.gauge("custom.cache.hitRate", nativeCache.stats().hitRate()); // hit
registry.gauge("custom.cache.evictionCount", nativeCache.stats().evictionCount()); // evict
});
}
}
이런 형태의 커스텀 코드를 통해 /actuator/metrics/custom.cache.size 와 같은 지표를 직접 조회할 수 있다고 한다.
여기에서 주입한 부분을 보면,
private final CaffeineCacheManager cacheManager;
이렇게 되어있다. 즉 CaffeineCacheManager에 대한 Bean 등록이 되어있어야 Spring이 제대로 돌아간다
이 Bean 주입은 CacheConfig 부분에서 할 수 있었음
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager caffeineCacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("userCache", "productCache");
cacheManager.setCaffeine(Caffeine.newBuilder()
.maximumSize(1000)
.recordStats()
.expireAfterWrite(10, TimeUnit.MINUTES));
return cacheManager;
}
}
여기에서,
public CacheManager caffeineCacheManager()
여기 타입부분을
public CaffeineCacheManager caffeineCacheManager()
이렇게 바꿔주면 CaffeineCacheManager에 대한 Bean 등록도 되고, 커스텀을 CaffeineCacheManager 형태로 사용할 수 있음
다만 예제에 맞게 CacheManager의 형태로 바꿔주자
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager caffeineCacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("userCache", "productCache");
cacheManager.setCaffeine(Caffeine.newBuilder()
.maximumSize(1000)
.recordStats()
.expireAfterWrite(10, TimeUnit.MINUTES));
return cacheManager;
}
}
이렇게!
그리고 Postman이나 브라우저 등으로 http://localhost:8080/actuator/metrics 를 get 요청해보면
{
"names": [
"application.ready.time",
"application.started.time",
"cache.eviction.weight",
"cache.evictions",
"cache.gets",
"cache.puts",
"cache.size",
"custom.cache.evictionCount",
"custom.cache.hitRate",
"custom.cache.size",
...
]
}
이런 형태로 custom 등록한 json 형태가 잘 나오고, 이를 get 요청하여 볼 수 있게 된다
참고할 코드
MeterRegistry.class
<T> Gauge gauge(Meter.Id id, @Nullable T obj, ToDoubleFunction<T> valueFunction) {
return (Gauge)this.registerMeterIfNecessary(Gauge.class, id, (id2) -> {
return this.newGauge(id2, obj, valueFunction);
}, NoopGauge::new);
}
팁
* 운영 환경에서는 Prometheus 및 Grafana를 함께 사용하여 실시간 시각화를 구축할 수 있음
* 캐시 미적중률이 갑자기 증가할 경우, TTL(만료 시간)이나 키 정책 변경 여부를 우선 확인할 수 있음
* 비즈니스 중요도가 높은 캐시는 별도의 알림(Alert) 기준을 설정해두면 안정적이라고 한다
정리
| 항목 | 설명 |
| /actuator/caches | 등록된 캐시 목록 및 상태 확인 |
| /actuator/metrics/cache.gets | 캐시 Hit / Miss 통계 조회 |
| /actuator/metrics/cache.evictions | 캐시 항목 제거 횟수 추적하기 |
| recordStats() | 캐시 통계 수집 활성화 |
| MeterRegistry | 커스텀 지표 등록 및 관리하기 |
'Spring Boot > Cache' 카테고리의 다른 글
| 캐시 모니터링과 문제 해결 : 일반적 캐시 문제와 해결 방법 (0) | 2026.01.15 |
|---|---|
| 캐시 모니터링과 문제 해결 : 캐시 성능 분석 (0) | 2026.01.15 |
| 로컬 캐시 구현과 최적화 : 로컬 캐시 성능 측정 (0) | 2026.01.12 |
| 로컬 캐시 구현과 최적화 : 로컬 캐시 구성 최적화 (0) | 2026.01.12 |
| 로컬 캐시 구현과 최적화 : 로컬 캐시 구현 옵션 (0) | 2026.01.12 |