학습 환경: 스프링 부트 3.1.5
0. 이 문서에서 다루는 것
- 로컬 캐쉬
- 스프링의 캐쉬 추상화
- 주요 객체 소개
- 간단한 예제
1. Cache Providers
스프링은 늘 기술 구현체를 직접 제공하지 않는다. 인터페이스와 서비스 추상화를 제공할 뿐이다.
스프링이 지원하는 캐쉬 제공자: https://docs.spring.io/spring-boot/docs/current/reference/html/io.html#io.caching.provider
여기서는 로컬 캐쉬를 사용하는 몇 가지만 다뤄보겠다.
- Simple
- Generic
- JCache (JSR-107)
1.1 Simple
https://docs.spring.io/spring-boot/docs/current/reference/html/io.html#io.caching.provider.simple
용도
- 테스팅
- 간단한 캐슁 시나리오
1.1.1 캐쉬를 사용하기 위한 최소한의 준비
의존성 추가
implementation "org.springframework.boot:spring-boot-starter-cache"
위 의존성을 기본으로, 앞으로 캐쉬 라이브러리의 의존성을 추가한다.
애너테이션 추가
@SpringBootApplication
@EnableCaching
아무런 캐쉬 라이브러리를 추가하지 않으면 SimpleCacheConfiguration 빈이 Auto-configuration(이하 자동 설정)되어, ConcurrentMapCacheManager 빈을 등록한다.
자동 등록되는 빈
- org.springframework.cache.annotation.ProxyCachingConfiguration
- org.springframework.cache.config.internalCacheAdvisor
- cacheOperationSource
- cacheInterceptor
- org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration
- cacheManager
- org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
- cacheManagerCustomizers
- cacheAutoConfigurationValidator
- spring.cache-org.springframework.boot.autoconfigure.cache.CacheProperties
1.1.2 Cache Manager
스프링의 캐쉬 매니저 SPI
주요 메서드
- @Nullable Cache getCache(String name)
- 캐쉬는 이름을 가질 수 있고 null일 수 있음을 알 수 있다.
- 캐쉬는 지연 생성될 수 있음
1.1.3 Cache
공통적인 캐쉬 작업을 정의한 인터페이스
메서드
- String getName()
- 캐쉬는 (논리적인) 이름을 가진다
- Object getNativeCache()
- Cache Provider를 반환한다
- ValueWrapper get(Object key)
- 키로 값을 가져온다. 키는 꼭 문자열일 필요는 없으며, 값은 래핑되어있다.
- 해당 키로 매핑된 것이 없다면 null을 반환한다.
- 매핑된 것이 있다면 그 값을 내포한 ValueWrapper 객체를 반환한다. 값 자체는 null일 수 있다.
- ValueWrapper 함수형 인터페이스를 제공하는 이유는 키가 매핑된 것이 없어서 null인지 값 자체가 null인지를 구분할 수 있도록 해주기 위해서인 듯 하다.
- void put(Object key, @Nullable Object value);
- 값은 null일 수 있다.
- void evict(Object key)
- ...
1.1.4 ConcurrentMapCacheManager
로컬 메모리에 캐슁하는 ConcurrentHashMap<String, ConcurrentMapCache> 타입의 캐쉬 저장소를 사용한다.
Cache getCache(String name) 메서드로 캐쉬 객체를 가져올 때 지정한 이름의 캐쉬를 기정의하지 않은 경우 새로 생성하여 반환한다. 하지만 spring.cache.cache-names 프라퍼티에 쉼표 구분으로 사용할 캐쉬명을 지정한 경우, 존재하지 않는 캐쉬 조회 시 null 반환한다.
1.2 Generic
https://docs.spring.io/spring-boot/docs/current/reference/html/io.html#io.caching.provider.generic
org.springframework.cache.Cache 타입의 빈을 직접 등록하면 동작하며, SimpleCacheManager가 사용된다.
용도
- 테스팅
- 간단한 캐슁 정의
자동 등록되는 빈
- org.springframework.cache.annotation.ProxyCachingConfiguration
- org.springframework.cache.config.internalCacheAdvisor
- cacheOperationSource
- cacheInterceptor
- org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration
- cacheManager
- org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
- cacheManagerCustomizers
- cacheAutoConfigurationValidator
- spring.cache-org.springframework.boot.autoconfigure.cache.CacheProperties
1.2.1 SimpleCacheManager
등록된 Cache 타입의 빈을 컬렉션으로 가지며, 로컬 메모리에 캐슁하는 ConcurrentHashMap<String, Cache> 타입의 캐쉬 저장소를 사용한다.
1.3 JCache (JSR-107)
https://jcp.org/en/jsr/detail?id=107
자바 진영의 캐쉬 추상화 표준인 Java Temporary Caching API
클래스패스에 JSR-107 준수 캐슁 라이브러리가 존재하면 동작한다.
- EhCache 3
- Hazelcast
- Infinispan
- Caffeine
- Apache JCS
javax.cache 패키지의 클래스도 필요하기 때문에 JSR107 API and SPI 의존성이 필요하다. spring-boot-starter-cache 부트 스타터 의존성을 추가하면 알아서 추가된다.
EhCache 3를 사용한다면, Eh107CacheManager가 사용되며 JCacheCacheManager는 래퍼로서 사용된다
자동 등록되는 빈
- org.springframework.cache.annotation.ProxyCachingConfiguration
- org.springframework.cache.config.internalCacheAdvisor
- cacheOperationSource
- cacheInterceptor
- org.springframework.cache.jcache.config.ProxyJCacheConfiguration
- org.springframework.cache.config.internalJCacheAdvisor
- jCacheInterceptor
- jCacheOperationSource
- org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration
- cacheManager
- jCacheCacheManager
- org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
- cacheManagerCustomizers
- cacheAutoConfigurationValidator
- spring.cache-org.springframework.boot.autoconfigure.cache.CacheProperties
1.3.1 Eh107CacheManager
로컬 메모리에 캐슁하는 ConcurrentMap<String, Eh107Cache> 타입의 캐쉬 저장소를 사용한다.
CacheManager 커스터마이징 방법은 2가지가 있다.
- spring.cache.cache-names 프라퍼티를 통해 사용할 캐쉬를 정의한다. javax.cache.configuration.Configuration 빈을 재정의한다.
- JCacheManagerCustomizer 빈들을 통해 완전한 커스터마이징 가능하다.
용도
- JVM 내 캐슁
- 일반적으로 Ehcache가 가장 많이 쓰이는 듯 하다.
- 로컬 캐슁
- 글로벌 캐슁을 원한다면 레디스를 사용하자.
1.3.2 Cache expiry, TTL
캐쉬는 기본적으로 만료되지 않는다. 캐쉬별 만료시간을 설정하여 캐쉬를 자동으로 삭제시킬 수 있다.
1.3.3 Value as object
지금까지는 캐쉬에 단순한 값만 저장하였는데, 객체도 저장할 수 있을까? 당연히 가능하다. 단, 객체는 직렬화되어야 하므로 Serializable 인터페이스를 구현해야 한다.
아직까지는 로컬 캐쉬를 사용하다 보니 직렬화에 어려움을 겪지 않는다.
1.3.4 Declarative annotation-based caching
스프링이 제공하는 애너테이션을 사용해 선언형으로 메서드의 반환값을 캐슁할 수 있다. 실무에서는 이 방식이 가장 많이 쓰인다.
참고
- Spring Boot
- https://docs.spring.io/spring-boot/docs/current/reference/html/index.html
- Caching: https://docs.spring.io/spring-boot/docs/current/reference/html/io.html#io.caching
- Auto-configuration: https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.developing-auto-configuration
- Spring Framework
- Ehcache
'Spring > Cache' 카테고리의 다른 글
| Spring > Cache > @Cacheable로 저장되는 데이터 자료구조 (0) | 2025.05.08 |
|---|---|
| Redis cache with Spring Boot (0) | 2023.11.17 |