EhCache 설정 및 사용 방법
dependencies { implementation 'org.springframework.boot:spring-boot-starter-cache' // https://mvnrepository.com/artifact/org.ehcache/ehcache implementation group: 'org.ehcache', name: 'ehcache', version: '3.10.0' }
spring: cache: jcache: config: classpath:ehcache.xml
<?xml version="1.0" encoding="UTF-8"?> <config xmlns='http://www.ehcache.org/v3'> <!-- 캐시를 저장할 디렉토리 위치 --> <persistence directory="${java.io.tmpdir}/ehcache-data/" /> <!-- 캐시의 템플릿, 이 템플릿을 각각의 캐시에 적용 --> <cache-template name="default"> <!-- 캐시 유지 시간 관리 --> <expiry> <tti unit="seconds">30</tti> </expiry> <!-- 캐시에 사용할 자원 정의 --> <resources> <!-- JVM heap 메모리, LRU --> <heap unit="MB">10</heap> <!-- JVM heap 메모리 외부의 메모리 --> <offheap unit="MB">50</offheap> <!-- disk 메모리, LFU --> <disk persistent="true" unit="GB">1</disk> </resources> </cache-template> <!-- 실제 적용할 캐시 정의 : exampleCache --> <cache alias="exampleCache" uses-template="default" > <!-- 사용할 키의 타입 정의 --> <key-type>java.lang.String</key-type> <!-- 캐시할 값의 타입 정의 --> <value-type>java.util.ArrayList</value-type> </cache> <!-- 실제 적용할 캐시 정의 : exampleCache2--> <cache alias="exampleCache2" uses-template="default" > <!-- 사용할 키의 타입 정의 --> <key-type>java.lang.String</key-type> <!-- 캐시할 값의 타입 정의 --> <value-type>java.lang.String</value-type> </cache></config>
package com.gsc.process.integration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; @SpringBootApplication @EnableCaching public class GscProcessIntegrationRunner { public static void main(String[] args) { System.out.println("Application for GSC Process Integration: Started."); SpringApplication.run(GscProcessIntegrationRunner.class, args); } }
@SuperBuilder @Data @EqualsAndHashCode(callSuper = false) @NoArgsConstructor @AllArgsConstructor @ApiModel(description = "공통 코드 모델") public class SampleApiModel implements Serializable { @ApiModelProperty("그룹 코드") private String grpCd; @ApiModelProperty("상세 코드") private String dtlCd; @ApiModelProperty("코드명") private String cdNm; @Data public static class Criteria { @ApiModelProperty("사용여부") private String useYn; } }
@Slf4j @Service public class SampleApiService { public List<SampleApiModel> getAll(SampleApiModel.Criteria criteria) { SampleApiModel model1 = new SampleApiModel("GRP_CD_000", "DTL_CD_000", "CD_NM_000"); SampleApiModel model2 = new SampleApiModel("GRP_CD_001", "DTL_CD_001", "CD_NM_001"); SampleApiModel model3 = new SampleApiModel("GRP_CD_002", "DTL_CD_002", "CD_NM_002"); SampleApiModel model4 = new SampleApiModel("GRP_CD_003", "DTL_CD_003", "CD_NM_003"); SampleApiModel model5 = new SampleApiModel("GRP_CD_004", "DTL_CD_004", "CD_NM_004"); List<SampleApiModel> list = new ArrayList<SampleApiModel>(); list.add(model1); list.add(model2); list.add(model3); list.add(model4); list.add(model5); return list; } @Cacheable(cacheNames = "exampleCache", key="#useYn") public List<SampleApiModel> getCache(String useYn) throws InterruptedException { Thread.sleep(3000); // Code for TEST! SampleApiModel model1 = new SampleApiModel("GRP_CD_000", "DTL_CD_000", "CD_NM_000"); SampleApiModel model2 = new SampleApiModel("GRP_CD_001", "DTL_CD_001", "CD_NM_001"); SampleApiModel model3 = new SampleApiModel("GRP_CD_002", "DTL_CD_002", "CD_NM_002"); SampleApiModel model4 = new SampleApiModel("GRP_CD_003", "DTL_CD_003", "CD_NM_003"); SampleApiModel model5 = new SampleApiModel("GRP_CD_004", "DTL_CD_004", "CD_NM_004"); List<SampleApiModel> list = new ArrayList<SampleApiModel>(); list.add(model1); list.add(model2); list.add(model3); list.add(model4); list.add(model5); return list; } @CacheEvict(cacheNames = "exampleCache", allEntries = true) public void evictCache() { log.info("delete all caches"); } }
@Slf4j @Api("OpenAPI for GSC Process Integration Project") @RestController public class SampleApiController { @Autowired SampleApiService sampleApiService; @GetMapping("/api/sample/return-map-api") @ApiOperation(value = "Map 반환 API", notes = "Map을 반환하는 API") public Map<String, Object> returnMapApi() { Map<String, Object> map = new HashMap<>(); map.put("test1", 1); map.put("test2", 2); return map; } @GetMapping("/api/sample/cmm-code") @ApiOperation(value = "공통 코드 반환", notes = "공통 코드 전체 리스트 반환") public List<SampleApiModel> getAllCommonCode(@ApiParam(value = "사용 여부", required = false, example = "Y") @RequestParam String useYn) { return sampleApiService.getAll(null); } @GetMapping("/api/sample/cache") @ApiOperation(value = "캐시 예제", notes = "EHCACHE 사용을 위한 예제") public List<SampleApiModel> getCache(@ApiParam(value = "사용 여부", required = false, example = "Y") @RequestParam String useYn) throws InterruptedException { long start = System.currentTimeMillis(); List<SampleApiModel> list = sampleApiService.getCache(useYn); long end = System.currentTimeMillis(); log.info("쿼리 수행 시간 : {}ms", end-start); return list; } @GetMapping("/api/sample/evict-cache") @ApiOperation(value = "캐시 삭제", notes = "EHCACHE 캐시 삭제 예제") public void evictCache() { sampleApiService.evictCache(); return; } }
- diskStore : 임시 저장 경로를 설정
- path : 경로
- sizeOfPolicy : Cache에 저장할 사이즈 정책 설정
- maxDepth : 최대값
- maxDepthExceededBehavior : continue: 초과 된 최대 깊이에 대해 경고하지만 크기가 조정 된 요소를 계속 탐색 /abort: 순회를 중지하고 부분적으로 계산 된 크기를 즉시 반환
- defaultCache : 기본 캐시 설정 (Required)
- eternal : "true" or "false"
- timeToIdleSeconds :
- timeToLiveSeconds :
- overflowToDisk : "true" / "false"
- diskPersistent : "true" / "false"
- memoryStoreEvictionPolicy : "LRU"
- cache : 사용하고자 하는 캐시 설정
- name: 코드에서 사용할 캐시 name (Required)
- diskExpiryThreadIntervalSeconds:
maxEntriesLocalHeap 메모리에 생성 될 최대 캐시 갯수 0
maxEntriesLocalDisk 디스크에 생성 될 최대 캐시 갯수 0
eternal 영속성 캐시 설정 (지워지는 캐시인지?)
external = “true”이면, timeToIdleSecond, timeToLiveSeconds 설정이 무시됨 false
timeToIdleSecond 해당 초동안 캐시가 호출 되지 않으면 삭제 0
timeToLiveSeconds 해당 초가 지나면 캐시가 삭제 0
overflowToDisk 오버플로우 된 항목에 대해 disk에 저장할 지 여부 false
diskPersistent 캐시를 disk에 저장하여, 서버 로드 시 캐시를 말아 둘지 설정 false
diskExpiryThreadIntervalSeconds Disk Expiry 스레드의 작업 수행 간격 설정 0
memoryStoreEvictionPolicy 캐시의 객체 수가 maxEntriesLocalHeap에 도달하면, 객체를 추가하고 제거하는 정책 설정
- defaultCache는 반드시 구현해야 할 캐시 (직접 생성하는 캐시에 대한 기본 설정)
- cache는 하나의 캐시를 사용할 때마다 구현
- name 속성은 캐시의 이름을 지정하며, 코드에서는 이 캐시의 이름을 사용하여 사용할 Cache 인스턴스를 구한다.
@EnableCaching 설정
```java
@Configuration
@EnableCaching(proxyTargetClass = true, mode = AdviceMode.PROXY)
public class EHCacheConfig {
@Bean
public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() {
EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("config/ehcache.xml"));
ehCacheManagerFactoryBean.setShared(true);
return ehCacheManagerFactoryBean;
}
@Bean
public EhCacheCacheManager ehCacheCacheManager(EhCacheManagerFactoryBean ehCacheManagerFactoryBean) {
EhCacheCacheManager ehCacheCacheManager = new EhCacheCacheManager();
ehCacheCacheManager.setCacheManager(ehCacheManagerFactoryBean.getObject());
return ehCacheCacheManager;
}
}
```
- @EnableCaching Annotation은 <cache:annotation-driven>와 마찬가지로 어노테이션 기반 캐시를 사용 할 수 있는 설정
- proxyTargetClass : class 기반 프록시를 생성함을 의미 (CGLIB라이브러리에 대한 의존성 필요)
- Mode : 어떤 Advisor 모듈을 선택할지에 대한 설정