오늘 알아 볼 내용은 Spring Boot의 Cache를 알아보자.
자주 읽기가 일어나는 곳에는 cache를 사용하는 것은 좋은 방법이라고 생각한다. 데이터베이스도 읽기 작업이 대부분이니 잘 사용하면 좋을 듯하다. 물론 아무대나 사용하지 말고 적당한 곳을 잘 고민해서 사용해야 될 것이다.
Spring Boot에서는 기본적으로 여러 서드파트 cache 라이브러리들을 지원한다. 꽤나 많은 캐시들을 지원하니 자신에게 맞는 캐시을 골라서 사용하면 된다. 기본적으로 지원할 뿐이지 만약 아래에 자신이 맞는 캐시가 없다면 따로 설정해주면 될 것같다.
일단
JSR-107
(JCache) 구현체들은 모두 지원한다. 스펙에 맞게 잘 구현되었다면 모두 지원하나 스펙에 맞지 않으면 장담하지 못할 듯하다. cache로 유명한
EhCache
도 지원하고
Hazelcast
,
Infinispan
,
Couchbase
,
Redis
,
Caffeine
,
Guava
등이 기본적으로 자동설정에 포함되어 있다. 참고할 사항은
Guava
캐시는 향후에는 지원을 하지 않을 예정이다. 1.5에서는
@Deprecated
되었고 2.0에서는 제거 되었다.
Spring에서는 추상화된 캐시를 지원하는데
CacheManager
라는 인터페이스이다.
CacheManager
인터페이스만 구현해주면 된다. 물론 그에 따른
Cache
도 구현해 줘야 한다.
기본적인 설정 방법이다.
spring-boot-starter-cache
를 디펜더시 받고
@EnableCaching
어노테이션을 선언하면 설정은 끝난다.
@SpringBootApplication
@EnableCaching
public class Application {
//blabla
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
기본적으로
spring-boot-starter-cache
이외에 아무 서드파트 라이브러리를 추가 하지 않느다면 기본설정인
SimpleCacheConfiguration
가 동작하며 CacheManager로는
ConcurrentMapCacheManager
가 빈으로 등록이 된다.
이 외 서드파트 디펜더시를 살펴보자.
아래는 caffeine cache 디펜더시 방법이다.
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
그 이외에 다른 서드파트 디펜더시들이다.
//redis
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
//couchbase
<dependency>
<groupId>com.couchbase.client</groupId>
<artifactId>java-client</artifactId>
</dependency>
<dependency>
<groupId>com.couchbase.client</groupId>
<artifactId>couchbase-spring-cache</artifactId>
</dependency>
//hazelcast
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-spring</artifactId>
</dependency>
좀 더 많은 서드파트 캐시들이 있으니 문서나 예제를 참고 하길 바란다. 설정하는 법은 알아봤으니 한번 사용해보자.
@Cacheable
어노테이션을 사용해서 캐시를 설정할 수 있다. 속성에는
value
,
key
,
condition
,
keyGenerator
,
cacheManager
등 여러개의 속성들이 존재한다. 좀 더 많은 속성이 있으니 문서를 참고하고 자주 사용하는 속성들만 작성하였다.
value
는 캐시의 이름을 나타내고,
key
는 캐시할 키를 지정하면 된다. 키를 지정하지 않을 경우에는 파라미터로 기본적인 키를 설정한다. 만약 파라미터가 여러개라면 모든 파라미터의 해시코드를 생성해 합쳐서 키로 만들어준다.
condition
은 특정 조건을 넣어서 상황에 따라 캐시를 할지 하지 않을지 결정하는 속성이다.
cacheManager
는 해당하는 cacheManager를 설정할 수 있다.
한번 사용해보자.
@Cacheable(value = "wonwoo", condition = "#name.length() < 10")
public String find(String name) {
logger.info("cache find .. {}", name);
return name;
}
만약 위와 같이 캐시를 설정 하였다면 캐시명은
wonwoo
되고 key는
name
이 된다. 그리고 파라미터(name)길이가 10보다 작을 때만 캐시를 한다고 설정 한 것과 같다.
@Cacheable(key = "#name", value = "wonwoo", condition = "#name.length() < 10")
위와 동일한 설정을 갖게 된다. 만약 Object 형태를 파라미터로 넘긴다면 모든 프로퍼티를 키로 사용해도 되지만 특정 프로퍼티만 사용하고 싶다면
SpEL
를 작성 하면 된다.
@Cacheable(key = "#myObject.name", value = "wonwoo", condition = "#name.length() < 10")
키 전략을 자신에 맞게 커스텀하여 만들 수 있는데 아래와 같이
keyGenerator
속성을 이용하면 된다.
@Cacheable(value = "wonwoo", condition = "#name.length() < 10", keyGenerator = "keyGenerator")
위와 같이 설정 한 후에
KeyGenerator
인터페이스 구현하고 빈으로 등록 해주면 된다.
public class MyGenerator implements KeyGenerator {
@Override
public Object generate(Object o, Method method, Object... objects) {
//blabla
}
}
이때 주의할 점은
key
와 같이 사용하면 안된다.
@Cacheable
어노테이션 말고
@CacheEvict
어노테이션도 존재하는데 이는 캐시 데이터를 삭제할 때 처리 하면 된다.
@CacheEvict(key = "#name", value = "wonwoo")
public String update(String name) {
logger.info("cache update .. {}", name);
return name;
}
특정 key의 데이터를 삭제하는 설정이다. 예를들어 key의 값이
123
으로 캐시된 값이 한개 있다고 가정해보자. 이를 삭제 하고 싶다면 name의 값을
123
으로 메서드를 호출 하면된다. 이 메서드가 호출 되고 나서 다시
@Cacheable
어노테이션의 메서드를 호출 한다면 (key:
123
) 메서드가 다시 호출 될 것이다.
만약 그 메서드의 캐시들을 모두 지워고 싶다면
allEntries
속성을 사용하면 된다.
@CacheEvict(key = "#name", value = "wonwoo", allEntries = true)
다음은
@CachePut
어노테이션이다. 이 어노테이션은 매번 메서드를 호출 한다. 하지만 호출과 동시에 캐시에 보관하므로 보통 저장할 때 용이할 듯하다.
@CachePut(key = "#name", value = "wonwoo")
public String save(String name) {
logger.info("cache save .. {}", name);
return name;
}
사용법은
@Cacheable
과 비슷하다. 속성 또한 거의 비슷하다.
하지만 같은 메서드에
@CachePut
과
@Cacheable
를 선언하는 것은 보통 권장하지 않는 방식이다. 순서가 꼬여 원하지 않는 동작이 발생할 수도 있으므로 같은 메서드에서는 쓰지 않도록 주의하자.
Spring의 더욱 자세한 캐시 사용법은 문서를 살펴보길 바란다.
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html
오늘 이상으로 Spring boot의 Cache 대해 알아봤다.