@Cacheable(value = [NEW_API], key = "{#userId}")
Spring Boot
를 사용하는 사람들이 Cacheable
어노테이션에 대해서 많이 보았을 것이고 사용도 해봤을 것이라 생각한다.
하지만 저 같은 경우는 Cache
가 어떻게 동작하는지? 어떤 상황에서 사용하면 좋은지? 효율적일지? 등등 자세히 알지 못하고 있었다.
그래서 이번 글에서는 Spring Boot
Cacheable
어노테이션을 사용하여 Cache를 적용하면서 잘 몰랐던 부분에 대해서 가볍게 정리해보려 한다.
GET /api/v1/news?userId=${userId}
user_id
를 파라미터로 외부 API를 호출해야 할 일이 있었다. 해당 외부 API의 응답 결과는 하루 동안 동일하기 때문에 캐시를 걸어야 겠다고 단순하게만 생각하였다.
그런데 위의 API에 캐싱을 거는 것은 잘못된? 부족한? 생각이었다. 이유는 아래와 같다.
@Cacheable(value = [NEW_API], key = "{#userId}")
내가 캐시를 작성했을 때 코드를 보면 위의 cacheKey
를 보면 userId
로 설정되어 있다. Cacheable
어노테이션을 통한 캐시는 서버의 메모리를 사용해서 캐싱하는데 하나의 서비스에 유저가 정말 많다면 위의 서버 메모리는 어떻게 될까?
최악의 상황으로 가정한다면 서버에 문제가 생길 수도 있을 것이다. 그리고 해당 캐시는 있어도 캐시의 역할을 못할 확률이 크다.
이유는 Cacheable
어노테이션은 LRU
기반으로 동작하는데 위처럼 userId
를 cacheKey
로 캐싱한다면 캐시 히트율이 정말 낮을 것이다.
- 유저 수가 많다면 불필요한 캐시 메모리를 차지 하게 된다.
- 유저 아이디로 캐시 키로 잡는다면 캐시 히트율이 매우 낮다.
LRU Cache 는 캐시에 공간이 부족할 때 가장 오랫동안 사용하지 않은 항목을 제거하고 새로운 것을 배치하는 형식으로 동작한다.
LRU Cache 의 전제 이론은 '오랫동안 사용되지 않은 항목은 앞으로도 사용되지 않을 가능성이 높기 때문에, 가장 오랫동안 참조되지 않은 것을 캐시에서 제거하자' 이다.
- 지금 와서 보면 이걸 왜 몰랐을까? 싶은 내용이지만 경험 및 개념 부족으로 바보 같은 생각 했던 것에 대한 정리를 해보았다.