BackEND/Java

Spring Boot에서 @Cacheable을 활용하여 캐시를 적용하는 방법

mingmingIT 2025. 3. 28. 10:30

이전 포스팅에서는 Spring Boot에서 캐시를 사용해야 하는 이유를 살펴보았습니다.

Spring Boot에서 캐시를 사용해야 하는 이유

이번 포스팅에서는 Spring Boot의 @Cacheable을 활용하여 실제로 캐시를 적용하는 방법을 단계별로 설명드리겠습니다.

1. Spring Boot에서 캐시 적용하기

Spring Boot에서는 @Cacheable을 사용하면 별도의 캐시 저장소 설정 없이도 간단하게 캐시를 적용할 수 있습니다. 기본적으로 메모리 기반 캐시가 제공되며, 필요에 따라 Redis, EhCache 등으로 변경할 수도 있습니다.

캐시 적용 순서

  1. Spring Boot 프로젝트에 캐시 기능 활성화
  2. @Cacheable을 사용하여 캐시 적용
  3. @CachePut과 @CacheEvict로 캐시 갱신 및 삭제
  4. 필요에 따라 캐시 저장소 변경 (예: Redis)

2. 캐시 설정 활성화 (@EnableCaching)

Spring Boot에서 캐시 기능을 사용하려면 @EnableCaching을 추가하여 캐시 기능을 활성화해야 합니다.

캐시 활성화 코드 (Config 클래스에 추가)

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableCaching  // 캐시 기능 활성화
public class CacheConfig {
}

이제 @Cacheable을 사용할 준비가 완료되었습니다.


3. @Cacheable을 활용한 캐싱 적용

이제 자주 호출되는 메서드에 @Cacheable을 적용하여 캐싱을 활성화해 보겠습니다.

캐시 적용 전 코드

@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;

    public Product getProduct(Long id) {
        System.out.println("DB에서 데이터를 조회합니다.");
        return productRepository.findById(id).orElseThrow();
    }
}

문제점:

  • getProduct() 메서드가 호출될 때마다 DB에서 데이터를 가져오므로 성능이 저하될 수 있습니다.
  • 동일한 요청이 반복될 경우 DB 부하가 증가할 수 있습니다.

@Cacheable을 사용하여 캐시를 적용해 보겠습니다.

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;

    @Cacheable(value = "products", key = "#id")
    public Product getProduct(Long id) {
        System.out.println("DB에서 데이터를 조회합니다.");
        return productRepository.findById(id).orElseThrow();
    }
}

@Cacheable 적용 후 특징

  • value = "products" → products라는 이름의 캐시 공간에 데이터를 저장합니다.
  • key = "#id" → 요청한 id 값을 키로 사용하여 캐시에서 데이터를 관리합니다.
  • 첫 번째 요청 시 DB에서 데이터를 가져오고, 이후에는 캐시에서 데이터를 가져오기 때문에 성능이 향상됩니다.

4. 캐시 갱신 및 삭제 (@CachePut, @CacheEvict)

캐시는 데이터를 저장하여 성능을 향상시키지만, 데이터가 변경될 경우 캐시를 갱신하거나 삭제해야 합니다.

이를 위해 @CachePut과 @CacheEvict을 사용할 수 있습니다.

4-1. @CachePut: 캐시 데이터 업데이트

 

  • @CachePut은 메서드가 실행될 때마다 DB에서 데이터를 가져와 캐시를 갱신합니다.
  • 기존 @Cacheable과의 차이점은, 항상 메서드를 실행한 후 결과를 캐시에 반영한다는 점입니다.

 

예제 코드

import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Service;

@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;

    @CachePut(value = "products", key = "#product.id")
    public Product updateProduct(Product product) {
        System.out.println("DB에서 데이터를 업데이트하고 캐시를 갱신합니다.");
        return productRepository.save(product);
    }
}

설명:

  • @CachePut을 사용하면 DB 업데이트 후 캐시도 자동으로 갱신됩니다.
  • @Cacheable과 다르게 항상 메서드가 실행됩니다.

4-2. @CacheEvict: 캐시 삭제

 

  • @CacheEvict은 캐시에 저장된 데이터를 삭제할 때 사용합니다.
  • 특정 데이터만 삭제할 수도 있고, 캐시를 모두 삭제할 수도 있습니다.

예제 코드

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;

@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;

    @CacheEvict(value = "products", key = "#id")
    public void deleteProduct(Long id) {
        System.out.println("DB에서 데이터를 삭제하고 캐시에서도 제거합니다.");
        productRepository.deleteById(id);
    }
}

 

설명:

  • 해당 상품이 삭제되면, DB뿐만 아니라 캐시에서도 삭제됩니다.
  • allEntries = true 옵션을 사용하면 해당 캐시에 저장된 모든 데이터를 삭제할 수도 있습니다.

모든 캐시 삭제 예제

@CacheEvict(value = "products", allEntries = true)
public void clearAllCache() {
    System.out.println("모든 캐시 데이터를 삭제합니다.");
}

5. 캐시 저장소 변경 (Redis 캐시 적용하기)

Spring Boot 기본 캐시는 메모리 기반이므로 서버가 재시작되면 캐시 데이터가 사라집니다.
Redis와 같은 외부 캐시 저장소를 사용하면 더욱 효율적으로 캐시를 관리할 수 있습니다.

Redis 캐시 설정 방법 (간단한 예제)
5-1. spring-boot-starter-data-redis 의존성 추가

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

5-2. Redis 캐시 설정 파일 추가

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.RedisConnectionFactory;

@Configuration
@EnableCaching
public class RedisCacheConfig {

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory();
    }

    @Bean
    public RedisCacheManager cacheManager() {
        return RedisCacheManager.create(redisConnectionFactory());
    }
}

5-3. @Cacheable을 그대로 사용하면, 이제 Redis에서 캐시가 저장되고 관리됩니다.


6. 결론

✅ @Cacheable을 사용하면 간단하게 캐시를 적용할 수 있습니다.
✅ @CachePut으로 캐시를 갱신하고, @CacheEvict으로 캐시를 삭제할 수 있습니다.
✅ 필요에 따라 Redis와 같은 외부 캐시 저장소를 활용하면 더욱 효율적인 캐싱이 가능합니다.