https://docs.spring.io/spring-framework/reference/integration/cache/strategies.html
https://docs.spring.io/spring-framework/reference/integration/cache/annotations.html
우테캠 쇼핑 미션 5단계인 외부 API 호출을 어떻게 처리할지 고민하다가 캐싱 적용을 고려하게 되었다. 다음은 스프링에서 캐싱을 어떻게 처리하는지 공식 문서를 읽고 필요한 부분만 정리한 내용이다.
버퍼와 캐시는 모두 속도가 빠른 장치와 느린 장치 간의 처리 속도 차이로 인한 비효율을 완화하는 임시적인 저장소이다. 그렇다면 어떤 점이 다른가?
스프링의 캐시 추상화는 메서드 단위로 적용된다. 메서드가 호출된 적이 있으면 캐시된 데이터가 반환되고 실제 호출은 이루어지지 않는다. 메서드가 호출된 적이 없으면 메서드가 호출되고 반환값이 캐시된다. 이 값은 나중에 재사용된다.
이를 통해 같은 파라미터로 메서드를 다시 호출하는 경우 이전의 결과를 재사용할 수 있다. CPU나 IO 자원을 많이 이용하는(추가적으로, 같은 인자에 대해 같은 결과를 반환하는) 메서드의 경우 캐싱을 이용하면 좋을 것이다.
스프링은 캐싱 로직에 대한 추상화만 제공하고 실제로 데이터를 저장할 저장소를 필요로 하는데 이는 Cache
, CacheManager
인터페이스로 구체화된다. 스프링은 ConcurrentHashMap
, Gemfire
, Caffine
등 몇 가지 구현체를 제공한다.
캐시 추상화를 사용하기 위해 두 가지 측면을 고려해야 한다.
value
필드에는 메서드와 연관되는 캐시 이름을 지정한다.@Cacheable("books")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
KeyGenerator
는 다음과 같이 키를 생성한다.SimpleKey.EMPTY
를 반환SimpleKey
객체를 반환equals
, hashcode
를 구현해야 함KeyGenerator
를 사용하고 싶다면 해당 인터페이스를 구현하면 된다.SpEL(Spring Expression Language)
를 사용할 수 있다.@Cacheable(cacheNames="books", key="#isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
@Cacheable(cacheNames="books", key="#isbn.rawNumber")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
@Cacheable(cacheNames="books", key="T(someType).hash(#isbn)")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
cacheManager
필드에 사용할 CacheManager
를 지정할 수 있다.sync
필드를 true
로 설정할 수 있다. 이를 사용하면 한 스레드가 값을 계산 중일 때 다른 스레드들을 블록할 수 있다.condition
필드와 unless
필드를 사용하면 조건적인 캐싱이 가능하다.@CachePut
과 @Cachable
을 함께 사용하면 안 된다. 예상하지 못한 동작을 유발할 수 있다.allEntries
필드를 true
로 지정하면 캐시 데이터가 전부 삭제된다. 이때는 키를 지정해도 무시된다.beforeInvocation
필드를 true
로 지정하면 메서드가 실행되기 전에 eviction이 일어난다.@Cacheable
과 다르게 메서드 반환 타입이 void
여도 상관없다.@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })
public Book importBooks(String deposit, Date date)
@CacheConfig("books")
public class BookRepositoryImpl implements BookRepository {
@Cacheable
public Book findBook(ISBN isbn) {...}
}
유익한 글이었습니다.