본문 바로가기

Spring

spring cache (1) 스프링 캐시 컨셉 이해하기

포스팅은 Spring Boot 공식 문서 CacheSpring Framework 공식 문서 Cache에 기반하여 작성하였습니다. 

 

JPA - 2차 캐시 알은 채 하기를 다룬적이 있었습니다. JPA는 캐시를 엔티티 단위로 접근합니다. 엔티티는 광범위하게 퍼져있기 때문에 캐시를 적용할 때는 생각해야할 부분이 너무 많아집니다. 반면 스프링 캐시는 메서드 단위로 캐시를 접근합니다. JPA에서 지원하는 2차 캐시를 손절(물론 프로젝트에도 적용 안함 ㅎ)하고 하루 빨리 스프링 캐시를 배우기로 한 가장 큰 이유입니다.

 

목차

1. 캐시 추상화 이해하기

2. Key Generation

3. 캐시 애노테이션

캐시 추상화 이해하기


Understanding the Cache Abstraction 부분을 정리한 내용입니다. 스프링 캐시에서는 메서드 단위의 캐싱을 지원합니다.

특정 메서드가 주어진 인자로 호출된 여부가 있는지 확인합니다. 만약에 호출된적이 있다면 해당 메서드를 실제로 호출하지 않고 결과를 반환합니다. 

 

예를 들어 아래와 같은 메서드가 있다고 합시다. readAll() 메서드는 인자로 page, size가 존재합니다.

@Cacheable(cacheNames = "study-products")
@GetMapping("/study-products")
public ResponseEntity<StudyProductApiReadResult> readAll(int page, int size) {
    List<StudyProductReadResponse> responses = studyProductReadService.readBy(PageRequest.of(page, size));

    return ResponseEntity.ok(new StudyProductApiReadResult(STUDY_PRODUCT_READ, responses));
}

 

제가 만약에 readAll(0, 10)을 호출한 적이 있다면 캐싱이 적용됩니다. 주의 할 부분은 해당 메서드 자체를 호출하지 않는다는 것입니다.

 

스프링 진영에서는 @EnableCaching 애노테이션을 통해 캐시 적용을 위한 인프라를 자동으로 구성해줍니다.

스프링 캐시를 이용할 때 특정 캐시 라이브러리를 추가하지 않으면 ConcurrentHashMap 인메모리 캐시를 사용하는 simple provider가 자동 설정된다. 공식 문서에서는 프로덕션 레벨에서 simple provider 사용을 권장하진 않지만 캐시를 이해하는데는 도움을 줄 것이라고 조언하고 있습니다.

 

스프링 진영에서 제공하는 캐싱 라이브러리는 Supported Cache Providers 를 참고해주세요.

 

 

Key Generation


캐시는 본질적으로 Key-Value 저장소기 때문에 적절한 Key 값을 만들어줘야 하는데요. 스프링의 기본 전략은 메서드에 들어가는 파라미터를 이용하는 것입니다.

 

  • If no parameters are given, return SimpleKey.EMPTY.
  • If only one parameter is given, return that instance.
  • If more than one parameter is given, return a SimpleKey that contains all parameters.

이렇게 설명하는데요. 없으면 SimpleKey.EMPTY 키를 사용하고 한개라면 해당 파라미터를 반환, 여러개라면 그것을 모두 포함하는 키를 만듭니다. Key는 hashCode() / Equals() 를 사용해서 만들어집니다.

 

@Cacheable key 파라미터를 이용하면 기본 키 생성 전략 수정할 수 있습니다.

@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)

key 파라미터에는 Spring Expression Language를 이용할 수 있습니다.

 

 

캐시 애노테이션


내용이 너무 방대하나 가성비가 그리 나오지 않을 것 같아 간단히만 설명하겠습니다.

 

@Cacheable

캐시에 대상을 추가하는 것입니다.  이를 통해 CPU 소모가 많거나 I/O 작업이 많이 들어가는 로직들에 대해 효율적으로 처리할 수 있습니다.

 

@CacheEvict

캐시는 항상 같은 결과를 반환하기 때문에 특정 상황에서 캐시를 초기화시켜줄 필요가 있습니다. 이럴 경우 캐시에서 대상을 비우는 @CacheEvict을 사용합니다.

 

이 외에도 @CachePut, @Caching 애노테이션이 있습니다.

 

마지막으로 캐시 애노테이션들의 파라미터들을 통해 key 생성 전략, 캐시 삭제/추가 조건만들기, 동기화, 캐시매니저 지정 등을 할 수 있습니다.