Spring

[Spring] Spring Cache

현인 2022. 9. 5. 14:32

Cache ?

캐시란 자주 사용하는 데이터를 저장해서 사용하는 기술를 뜻합니다.

캐시는 동일한 요청에 유사한 내용의 데이터를 반복적으로 반환해야 할 때 사용합니다.

 

간단히 설명하자면, 어느 한 교실에 학생과 선생님이 있습니다. 학생이 선생님에게 궁금한 점을 한 가지 질문하고 선생님은 학생에게 답변을 해줍니다. 하지만 학생이 매일매일 똑같은 질문을 또 반복합니다.

 

여기서 만약 학생이 선생님에게 한 질문의 답을 메모를 통해 질문에 대한 답을 기억했더라면, 굳이 선생님께 다시 질문을 하지 않았을 겁니다.

 

캐시는 이럴 때 필요합니다.
동일한 리소스(궁금증)를 반복적으로 조회(질문) 하게 되면 DB(선생님)에 부담이 되겠죠,
하지만 이 리소스를 따로 메모(저장) 해두어 조회할 때마다 DB가 아닌 메모를 통해 빠르게 해결하면 DB에 부담도 줄어들 수 있고 학생도 더 빠르게 궁금증을 해결할 수 있겠죠

Look-Aside / Write-Around 캐싱 전략

Spring Local-Memory 로 다뤄볼 캐싱 전략은 Look-Aside / Write-Around 전략으로, 범용적으로 많이 사용됩니다.

  • Look-Aside 읽기 전략은 데이터를 찾을 때 캐시를 먼저 확인하고 캐시가 존재하면 바로 반환합니다. 만약 캐시에 존재하지 않으면 DB를 조회해서 반환합니다.
  • Write-Around 쓰기 전략은 데이터를 저장할 때 캐시를 거치지 않고 바로 DB에 저장하도록 합니다.

실전😎

dependency 추가

build.gradle에 의존성을 추가하는 것으로 bean 설정이 자동으로 끝나게 됩니다. 이후 추가적인 커스터마이징이 있을 수 있으니 bean 설정을 직접 하도록 합니다!

CacheConfig

Cache 빈 설정

ConcurrentmapCache name 부분은 캐시 저장소의 이름을 뜻합니다.
ConcurrentMapCache 클래스는 null 값 캐싱 여부를 생성자를 통해 결정할 수 있습니다.

ConcurrentMapCache

이렇게 설정이 마무리 되었고, 기능을 추가하면 된다.
ConcurrentCache는 만료시간이 존재하지 않는다. 따라서 만료가 필요한 캐싱이라면 Scheduling 또는 만료 시간을 직접 지정하는 방향으로 구현해야 합니다.

@Cacheable

캐시는 기본적으로 Map을 상속받아 Key Value로 구성되어 있습니다.
따라서 Key 값은 DB에서 조회한 데이터가 들어있는 Key 값이며 이 Key를 통해 데이터를 검색하여 반환합니다.

  • key : 캐시에 저장할 key 값, 메소드의 인자값
  • cacheNames : 저장할 캐시 저장소의 이름, CacheConfig 에 작성한 이름

@Cacheable을 Get 메소드에 명시하면 자동으로 값을 조회할 때 Look-Aside 읽기 전략으로 동작합니다. Cache Hit이 이루어질 때는 메소드의 실행이 이루어지지 않는다.

findUsers Service Logic

따라서 위 코드를 같은 id로 두 번 실행했을 때 처음에만 log가 출력되고 두 번째에는 Cacheable의 Cache Hit이 실행될 때에는 메소드가 실행되지 않아 log가 출력되지 않는다.

  • Cache Hit : 캐시에 해당 값이 있을 경우 캐시에서 해당 정보를 꺼내서 반환
  • Cache Miss : 캐시에 값이 없으면 DB에서 읽어온 데이터를 캐시에 저장

@CachePut

@CachePut@Cacheable 과 같이 캐싱을 하는 어노테이션입니다.
하지만 @Cacheable과의 차이점은 Cache Hit을 하더라도 메소드를 동작한다는 것입니다.

 

위에서 봤던 이 코드로 예를 들자면,
@Cacheable는 Cache Hit이 이루어지면 더 이상 해당 메소드가 실행되지 않아 log가 출력되지 않지만
@CachePut은 Cache Hit이 이루어져도 해당 메소드가 실행되어 log가 출력되게 됩니다.

 

또한 지정된 캐시 저장소(UserStorage)의 key에 대한 value를 업데이트할 때에도 사용됩니다.

@CacheEvict

캐시 저장소에 저장된 key 값에 대한 value를 삭제할 때 사용합니다.

key = "#key" 로 사용하는 이유

바로 key는 SpEL (Spring Expression Language) 문법을 사용하기 때문입니다.
기본적인 Primitive Type은 #변수명 의 형태로 가능하며, 객체 안의 멤버변수를 비교해야 할 경우 #객체명.멤버명 의 형태로 접근 할 수 있습니다.

조건

condition 속성을 이용하면 캐싱되는 조건도 부여할 수 있습니다.

예제 코드

아래의 깃헙 주소에 해당 코드가 있습니다 :)

https://github.com/honghyunin/Spring-Cache

 

Reference 🙇‍♂️

https://jistol.github.io/spring/2017/02/09/springboot-cache-key/
https://loosie.tistory.com/806
https://sunghs.tistory.com/132

'Spring' 카테고리의 다른 글

DI를 쓰려면 꼭 IoC를 써야할까?  (0) 2022.12.20