Guava로 Cache 적용하기
Guava로 Cache 적용하기
Java application 개발 중 간혹 cache를 적용해야 할 때가 있다. 어떻게 할까… 순간 많은 로직이 뇌리를 스치고 지나간다.
Static 한 map을 만들고, hit 하면 반환 - 못하면 DB 조회, 시간이 오래되면 갱신 등등… 비즈니스 로직을 구현하기도 바쁜데 제대로 동작할지 모르는 cache를 직접 구현하려니 막막하다.
이럴 때 우리들의 든든한 형, Google 형님이 계신다. Google 형님은 우리들의 하찮은 시간을 보전하라고 Guava라는 Java 용 라이브러리를 만들어 주셨다.
Guava, 아마 Google + Java가 아닐까?
Guava의 Caches
Guava의 Caches는 대략 CacheBuilder와 CacheLoader로 구분됨
- CacheBuilder: Cache를 만들어 주는 Builder class, cache의 크기, life-cycle 등(eviction)과 세부 커스텀 동작을 정의
- CacheLoader: Cache를 거쳐 제공할 데이터 조회(population)를 정의
구현
- 예제는 Guava GitHub에 자세하게 설명되어 있음
- 정의 예제
LoadingCache<String, User> users = CacheBuilder.newBuilder() .maximumSize(10) .expireAfterWrite(10, TimeUnit.MINUTES) .build( new CacheLoader<String, User>() { @Override public Map<String, User> loadAll(Iterable<? extends String> keys) throws Exception { ... return userDaoService.getMap(keys); } @Override public User load(String key) throws Exception { ... return userDaoService.get(key); } });
- Inline으로 작성되어 있지만, CacheLoader는 별도의 class로 상속받아 구현해두면 향후 유지보수가 쉬울 것
- CacheBuilder는 LoadingCache 객체를 생성하는데, LoadingCache는 get(), getAll(), refresh()등 필요한 기능을 다 갖추고 있음
- Cache 값 반환은 Guava의 ImmutableMap(불변, 변경할 수 없는 map) 타입으로 함
- CacheBuilder에서 직접 cache값을 입력하거나, cache에 없을 때 수행할 메소드 설정(callable), refresh 설정, 삭제된 데이터 반영(removal listner) 등 다양한 튜닝도 가능
- 사용
@Autowired private LoadingCache<String, User> userCache; ... Set<String> userIdSet = new HashSet<>(Arrays.asList("111", "222")); ImmutableMap<String, User> userMap = userCache.getAll(userIdSet);
- getAll() 수행 시, 없는건 loadAll로 찾아서 함께 반환
결론
어쨌든 좋은 도구들은 미리 만들어져 있으니 우리는 비즈니스 로직에 집중하면 된다.