이끌든지 따르든지 비키든지

Framework/Spring

[Spring] 스프링의 캐시 추상화

SeongHo5 2024. 3. 17. 21:04

들어가기 앞서 - 캐시(Cache)란?


 

캐시(Cache)는 데이터 빠르게 접근하기 위해 임시로 저장하는 공간 입니다. 캐시는 자주 사용되는 데이터나 결과를 저장해 두었다가, 동일한 요청이 들어올 때 빠르게 응답할 수 있게 도와줍니다. 이는 데이터베이스나 외부 시스템에 대한 접근 횟수를 줄여 시스템의 전체적인 성능을 향상시킬 수 있습니다.

 

스프링에서는 이러한 캐시의 사용과 관리를 쉽게 만들어주는 캐시 추상화를 제공합니다.

스프링의 캐시 추상화는 다양한 캐시 저장소를 지원하며, 개발자가 캐시 로직을 쉽게 구현하고 관리할 수 있도록 지원합니다.

 

💡캐시 추상화란?
캐시 추상화는 캐시 구현을 애플리케이션 로직으로부터 분리하여, 개발자가 캐시를 보다 쉽게 사용할 수 있도록 하는 개념입니다.
어노테이션을 사용하여 메소드 레벨에서 쉽게 캐시를 적용할 수 있게 해주며, 캐시의 생성, 조회, 갱신, 삭제 등의 작업을 투명하게 처리합니다.

 

 

 

Spring에서 캐시 구성하기


 

Spring이 지원하는 Cache Provider 종류

  • Generic: 기본적인 캐시 구현으로, 특별한 설정 없이 사용할 수 있습니다.
  • JCache (JSR-107): JCache 인터페이스를 구현하는 여러 캐시 기술(EhCache 3, Hazelcast, Infinispan 등)을 지원
  • Hazelcast
  • Infinispan
  • Couchbase: 문서 지향 데이터베이스
  • Redis
  • Caffeine
  • Simple: Spring이 제공하는 간단한 구현체 (ConcurrentHashMap으로 구현됨)

@EnableCaching 어노테이션이 활성화되었고, CacheManger나 CacheResolver 유형의 Bean이 구성되지 않은 경우, 위 순서대로 캐시 제공자를 탐색합니다.

 

※ 출처 및 더 자세한 정보 ▼

 

33. Caching

The cache abstraction does not provide an actual store and relies on abstraction materialized by the org.springframework.cache.Cache and org.springframework.cache.CacheManager interfaces. If you have not defined a bean of type CacheManager or a CacheResolv

docs.spring.io

 

 

캐시 설정 추가 (Redis를 사용하는 경우)

@EnableCaching
@Configuration
public class CacheConfig {
	
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        return RedisCacheManager.builder()
                .transactionAware() // 캐싱도 트랜잭션 내에 포함될 수 있도록 설정
                .cacheDefaults(defaultCacheConfig())
                .build();
    }
    
	@Bean
	protected RedisCacheConfiguration defaultCacheConfig() {
		return RedisCacheConfiguration.defaultCacheConfig()
			.entryTtl(Duration.ofMinutes(30)) // 유효기간 설정
			.disableCachingNullValues(); // null은 캐싱하지 않도록 설정
    }

}

 

 

 

캐시 활용하기


@Cacheable

이 어노테이션이 붙은 메서드는 실행될 때 캐시를 확인하고, 캐시된 값이 있으면 그 값을 반환합니다. 

캐시된 값이 없으면 메서드가 실행되고, 그 결과를 캐시에 저장합니다.

 

@Cacheable("books")
public Book findBook(ISBN isbn) {
    // DB에서 책 정보 조회
    return bookRepository.find(isbn);
}

 

 

@CachePut

메서드의 결과를 캐시에 강제로 새로 쓰는 데 사용됩니다. 이 어노테이션이 붙은 메서드는 매번 실행되며, 그 결과는 항상 캐시에 저장됩니다.

 

 

@CacheEvict

캐시에서 항목을 제거할 때 사용됩니다. 데이터가 변경될 때 캐시의 일관성을 유지하기 위해 주로 사용됩니다.

 

 

 

옵션

  • cacheNames: 캐시를 식별하고 구분하는 데 사용
  • key: 캐시의 Key 이름을 설정
  • condition: 캐싱을 적용할 조건 설정 
  • unless: 메서드의 반환 값에 대한 조건 설정 
  • sync: 동시성 관리를 위한 옵션 / 하나의 키에 대해 하나의 스레드만 캐시 업데이트를 수행합니다.
  • 그 외, keyGenerator, cacheManager, cacheResolver 등

 

옵션 중, key / condition / unless 옵션에는 SpEL을 적용해 동적으로 설정을 적용할 수 있습니다.

 

 

@Cacheable(value = "userCache", key = "#userId", unless = "#result.age < 18")
public User findUser(String userId) {
    // 사용자 정보 조회
    return userRepository.findById(userId);
}

 

 

이 메서드는,

  • 메서드의 파라미터 userId를 캐시의 Key로 사용합니다. 사용자 ID별로 캐시 정보를 관리할 수 있습니다.
  • 반환하는 사용자의 age 속성이 18 미만인 경우, 결과를 캐싱하지 않습니다.

이러한 방법으로 SpEL을 활용해 동적으로 캐싱 동작을 제어할 수 있습니다.

 

💡SpEL이란?

 

[Spring] SpEL으로 더 강력하게 표현식 작성하기

SpEL이란? Spring Expression Language(SpEL)은, 객체 그래프를 조회하고 조작하는 데 사용되는 표현식 언어입니다. SpEL을 사용해 런타임에 객체의 속성에 접근하거나, 메서드를 호출하거나, 배열, 리스트

seongho-jo-5.tistory.com