spring cache 를 사용 하기 위한 ehcache 사용법
강준한 입니다.
감동을 줄 뻔한 이야기로 시작해보죠.
아들이 치매에 걸린 아버지와 같이 있습니다.
아버지는 멀리 있는 새를 보고 아들에게 물었습니다,
저게 무어냐?
아들이 말하죠...
까마귀요...
잠시 뒤, 치매에 걸린 아버지가 다시 물었습니다,
저게 무어냐?
아들이 다시 말하죠...
까마귀 라니까요
아버지는 잠시 뒤 다시 물었습니다
저게 뭐라고?
아들은 짜증이 났습니다.
까마귀라고요. 까!!마!!귀!!
아버지는 잠시 뒤 다시 물었습니다
저게 무어냐?
아들은 화를내며 큰소리로 말합니다.
까마귀라고요! 까마귀. 왜 자꾸 같은 SELECT를 반복하세요!!
그렇습니다 ... 아들에게는 cache가 적용되어 있지 않았던 것입니다.
그래서 화(부하)가 발생했던 것입니다.
cache는 이런 간단하고 반복된 답을 줘야 하는 내용을 어느 한켠에 저장 했다가
바로 꺼내어 줄수 있는 방법입니다.
스프링에서는 아주 간단하게 사용이 가능 합니다.
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-cache', version: '2.7.9'
종속성을 먼저 추가 한 후에 사용 하시면 됩니다.
물론 예시라서 따라 치면 오류납니다.
이 캐시의 어노테이션의 종류는 5가지 정도가 있습니다.
@Cacheable : 동일한 파리 미터로 메서드를 호출 이력과 반환 결과가 캐시에 저장되어 있으면
@CacheEvict : 캐시에 저장된 호출 이력 및 결과 값을 삭제
@CachePut : 캐시에 저장된 결괏값을 업데이트
@Caching : 여러 개의 캐시 어노테이션 옵션을 동시에 활성화하고자 할 때 사용
@CacheConfig : 캐시 옵션을 메서드 단위가 아닌 클래스 단위로 설정하고자 할 때 사용
그림에서 사용한 @Cacheable 키 벨류로 데이터를 저장하고 사용 되겠죠 마치 맵과 같네요
키를 안쓰면 뭐 그 안의 알고리즘으로 자동 생성 된다고 합니다.
선언후에 삭제 하거나 변경하는 작업을 주로 쓰겠죠? 사용 시점에 잘 분배해서 사용 하시면 될 것같습니다.
주로 많이 사용 하는 게시판을 예로 들면 리스트를 불러올때 @Cacheable 을 선언할 것이고
insert나 업데이트를 할때 캐시를 업데이트 할테고 ... delete 할때는 캐시를 비웠다가 다시 리스트를 불러올때 선언 하겠죠? ( 맞을까? )
하지만 사용 하다보면 각 상황에 맞는 포인트를 찾기 쉽지 않아 제때 알아서 한번씩 비워주고 다시 생성 됬으면 합니다.
물론 자동으로요
여기저기 구글링을 하다 보니 ehcache 라는 녀석이 눈에 띕니다. redis 캐시도 눈에 뛰구요
하지만 과하게 가지 않고 로컬에 저장되고 사용되길 원하니 ehcache 를 사용 해봅니다. 종속성을 추가 해줍니다
implementation group: 'org.ehcache', name: 'ehcache', version: '3.10.0'
/***
private String soliloquy() throws Exception {
return "속으론 여러번 고민한게 있었는데 이거는 그냥 쓸데없는거같지만 뭐랄까....
메모리를 사용하는 레디스 캐시를 사용하면 1유저의 세션을 저장한다고 했을때 용량산정에
대한?? 이게 고민 할 문제가 맞을까요 ...? .. 암튼";
}
***/
버전은 자유겠지요 ... 저는 https://mvnrepository.com/ 에서 종속성을 검색한 후에 최근 몇개월간 중 많이 사용된 버전을 주로 사용 합니다. 전세계 테스터들이 좋으니까 썻겟죠?
ehcache 설정은 많이 검색해봤지만 xml 설정 만 나오는 거같아요
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<diskStore path="io.dveamer.sample.ehcache"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
</ehcache>
전부 모르겠고 중요해 보이는
maxElementsInMemory : 수치는 모르겠지만 찾아보니 바이트 단위 인듯 합니다
timeToIdleSeconds : 120초 동안 재요청이 없으면 비우고
timeToLiveSeconds : 120초 동안 살려 놓는다는 뜻인가 보네요
xml 설정은 JAVA CONFIG로 변경 해봅니다
import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.ExpiryPolicyBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.MemoryUnit;
import org.ehcache.jsr107.Eh107Configuration;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.cache.CacheManager;
import javax.cache.Caching;
import javax.cache.spi.CachingProvider;
import java.time.Duration;
@EnableCaching
@Configuration
public class CacheConfig {
@Bean
public CacheManager EhcacheManager() {
CacheConfiguration<String, Object> cachecConfig = CacheConfigurationBuilder
.newCacheConfigurationBuilder(String.class,
Object.class,
ResourcePoolsBuilder.newResourcePoolsBuilder()
.offheap(10, MemoryUnit.MB)
.build())
.withExpiry(ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofSeconds(3600)))
.build();
CachingProvider cachingProvider = Caching.getCachingProvider();
CacheManager cacheManager = cachingProvider.getCacheManager();
javax.cache.configuration.Configuration<String, Object> configuration = Eh107Configuration.fromEhcacheCacheConfiguration(cachecConfig);
cacheManager.createCache("test", configuration);
return cacheManager;
}
}
여기서는 offheap 에 10 메가로 설정했고
재요청이 3600초 동안 없으면 지우는 걸로 설정 했어요
.withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(3600))));
을 추가 하기 전에 이걸로 테스트 해보려 합니다 . 재요청이 계속 있으면 죽이 않는지 ..
그리고 나서 케시 이름을 지정하여 생성 해줍니다
저는 test를 만들어놓고 사용해봅니다
위에
이렇게 사용 벨류에 케시 이름으로 만들어논 캐시 영역을 사용 하시면 됩니다.
지금까지 테스트는 잘되고 잘 캐싱이 되고 있는데
문제가 생기면 같은걸로 다시 포스팅 해보겠습니다.
그럼 이만