1. 캐시란
캐시는 서버의 부담을 줄이고, 성능을 높이기 위해 사용되는 기술이다.
캐시는 값을 저장해두고 불러오기 때문에 반복적으로 동일한 결과를 반환하는 경우에 용이하다.
만약 매번 다른 결과를 돌려줘야 하는 상황에 캐시를 적용한다면 오히려 성능이 떨어지게 된다.
오히려 캐시에 저장하거나 캐시를 확인하는 작업 때문에 부하가 생기기 때문이다.
그러므로 캐시는 동일한 결과를 반환하는 반복적인 작업과 시간이 오래 걸려서 서버(애플리케이션)에 부담이 되는 경우에 적용하면 좋다.
2. Spring AOP
스프링은 AOP 방식으로 편리하게 메소드에 캐시 서비스를 적용하는 기능을 제공하고 있다.
이를 통해 캐시 관련 로직을 핵심 비즈니스 로직으로부터 분리할 뿐만 아니라, 손쉽게 캐시 기능을 적용할 수 있다.
또한 스프링은 캐시 구현 기술에 종속되지 않도록 추상화된 서비스를 제공하고 있다.
그렇기 때문에 환경이 바뀌거나 적용할 캐시 기술을 변경하여도 애플리케이션 코드에 영향을 주지 않는다.
3. 캐싱 적용방법
Spring에서 @Cacheable과 같은 어노테이션 기반의 캐시 기능을 사용하기 위해서는 먼저 다음과 같이 ‘spring-boot-starter-cache' 라이브러리의 의존성을 추가해야 한다.
Spring에서 어노테이션 기반의 캐시 기능을 사용하려면, @EnableCaching 어노테이션을 설정 클래스에 추가해주어야 한다.
@EnableCaching 은 Spring Boot 애플리케이션에서 캐싱을 활성화하는데 사용되며, @Configuration이 포함된 클래스에서 이를 적용한다.
그 후에는 캐시를 관리해줄 CacheManager를 빈으로 등록(by @Bean)해주어야 한다.
CacheManager는 캐시를 관리하고 캐시된 데이터를 저장하고 반환하는 역할을 한다.
Spring에서는 여러가지 CacheManager 를 제공해주고 있는데, 종류에 따라 메모리 상 또는 디스크/데이터베이스에 캐시를 저장할 수 있고, Redis, Ehcache, Caffeine 등 다양한 캐시 라이브러리와 연동하여 사용할 수 있다.
지금 개발하고 있는 프로젝트에서는 아직 단일 서버를 운영하고 있기 때문에, 메모리 상에 캐시를 저장하는 ‘로컬 캐시’ 방식을 택한 ConcurrentMapCacheManager 를 사용하기로 했다.
@Cacheable 어노테이션은 캐시를 저장 및 조회하는 데 사용된다.
클래스나 인터페이스에도 캐시를 지정할 수는 있지만, 보통은 메소드 단위로 적용한다.
캐시를 적용할 메소드에 @Cacheable 어노테이션을 붙여주면, 캐시에 데이터가 없을 경우에는 기존의 메소드를 실행한 후에 캐시를 추가하고, 캐시에 데이터가 없으면 메소드를 실행하지 않고 캐시의 데이터를 반환한다.
4. 테스트
다음은 서울시 폐의약품 수거함 위치 정보를 조회하는 메소드의 실행시간을 캐시가 있을 때와 없을 때를 비교하여 테스트해본 결과이다.
@BeforeEach 로 테스트 전에 캐시를 삭제하고 서울시 폐의약품 수거함 위치 정보를 저장한다.
따라서 처음 getSeoulDrugBinLocations() 메서드가 실행될 때에는 캐시가 없고 이 때에는 실행시간이 179ms가 걸렸다.
이후에 바로 같은 메소드를 실행할 때에는 캐시가 저장되어 있으므로 실행시간이 1ms로 급격히 줄어들었다.
Reference
https://www.baeldung.com/spring-cache-tutorial