ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring, Spring Boot] 데이터 캐싱(Caching)
    Spring 2024. 12. 11. 11:15

    Spring Boot에서 데이터 캐싱(Caching)은 데이터베이스나 외부 API에서 자주 조회하는 데이터임시 저장소에 저장하여 애플리케이션의 성능을 향상시키는 기술입니다. 캐싱을 통해 불필요한 데이터 조회를 줄이고, 응답 속도를 크게 개선할 수 있습니다.

     

    Spring Boot에서 캐싱 구현 방법

    캐싱 활성화

    • Spring Boot 애플리케이션 클래스에 @EnableCaching 어노테이션을 추가하여 캐싱 기능을 활성화합니다.
    @SpringBootApplication
    @EnableCaching // ---> 캐싱 사용
    public class CachingApplication {
        public static void main(String[] args) {
            SpringApplication.run(CachingApplication.class, args);
        }
    }

     

    캐시 저장소 설정

    • Spring Boot는 기본적으로 ConcurrentHashMap을 캐시 저장소로 사용하지만, Redis, Ehcache, Caffeine 등의 외부 캐시를 통합할 수도 있습니다.

    캐싱 어노테이션 사용
    Spring에서 제공하는 캐싱 관련 어노테이션을 사용하여 캐시를 쉽게 구현할 수 있습니다:

    • @Cacheable: 캐시에서 데이터를 조회하거나, 없으면 메서드를 실행하고 결과를 캐시에 저장합니다.
    @Service
    public class ProductService {
        @Cacheable("products")
        public Product getProductById(Long id) {
            // 데이터베이스 조회
            return productRepository.findById(id).orElseThrow();
        }
    }

     

    • @CachePut: 메서드를 실행하고, 결과를 캐시에 저장하거나 업데이트합니다.
    @CachePut(value = "products", key = "#product.id")
    public Product updateProduct(Product product) {
        return productRepository.save(product);
    }

     

    • @Caching: 여러 캐싱 규칙을 조합하여 사용합니다.
    // 캐시 무효화(Cache Eviction) 
    @Caching(evict = {
        @CacheEvict(value = "products", key = "#id"),
        @CacheEvict(value = "categories", allEntries = true)
    })
    public void deleteProduct(Long id) {
        productRepository.deleteById(id);
    }
    
    /**
     @CacheEvict (첫 번째):
        value = "products": products라는 이름의 캐시에서 무효화 작업을 수행합니다.
        key = "#id": 삭제할 캐시 항목의 키를 메서드의 매개변수 id 값으로 지정합니다.
            예: deleteProduct(5L)을 호출하면 products 캐시에서 키가 5L인 항목이 삭제됩니다.
    */
    
    /**
    @CacheEvict (두 번째):
        value = "categories": categories라는 이름의 캐시에서 무효화 작업을 수행합니다.
        allEntries = true: 캐시에 저장된 모든 항목을 삭제합니다.
            특정 키가 아니라, categories 캐시 전체를 비웁니다.
    */

     

     

    캐싱의 장점

    1. 응답 속도 향상:
      • 반복적인 데이터 조회를 줄여 요청 처리 속도를 크게 개선.
    2. 데이터베이스 부하 감소:
      • 데이터베이스나 외부 API 호출을 줄여 리소스 사용을 최적화.
    3. 비용 절감:
      • 대규모 트래픽 환경에서 캐싱을 활용하면 비용을 줄일 수 있음.

     

    캐싱의 단점

    1. 데이터 불일치(Inconsistency):
      • 캐시 데이터와 원본 데이터가 일치하지 않을 수 있음. 이를 해결하기 위해 캐시 갱신 전략 필요.
    2. 메모리 사용량 증가:
      • 캐싱 저장소가 제한된 메모리를 소비하므로 효율적인 관리가 필요.
    3. 복잡성 증가:
      • 캐싱 전략과 관리가 잘못되면 성능 저하나 예기치 않은 문제가 발생할 수 있음.

     

     

    @CacheEvict와 @CachePut의 비교

    @CacheEvict@CachePut는 Spring의 캐싱 관리에서 사용하는 두 가지 주요 어노테이션입니다. 각각의 동작 방식과 활용 목적, 장단점을 비교해보겠습니다.

     

    @CacheEvict

    동작 방식:

    • 캐시에서 데이터를 삭제(무효화)합니다.
    • 데이터를 삭제하여 캐시에 더 이상 사용할 수 없도록 만듭니다.

    장점:

    1. 불필요한 데이터 제거:
      • 더 이상 유효하지 않은 데이터를 캐시에서 완전히 삭제하므로, 잘못된 데이터가 참조되는 것을 방지합니다.
    2. 단순성:
      • 캐시의 특정 항목이나 전체 항목을 간단히 삭제할 수 있습니다.
    3. 명시적 무효화:
      • 데이터베이스에서 삭제된 데이터에 대해 캐시 항목을 정확히 제거할 수 있습니다.

    단점:

    1. 재조회 필요:
      • 삭제된 항목을 다시 사용할 경우, 데이터베이스에서 새로 조회하여 캐시에 저장해야 하므로 추가적인 처리 비용이 발생할 수 있습니다.
    2. 캐시 효율성 저하:
      • 캐시가 비어 있는 경우 데이터베이스에 대한 호출 빈도가 증가할 수 있습니다.

     

    @CachePut

    동작 방식:

    • 캐시를 무효화하지 않고, 캐시에 데이터를 업데이트합니다.
    • 메서드가 실행된 결과를 캐시에 저장하며, 기존 데이터가 있으면 덮어씁니다.

    장점:

    1. 항상 최신 데이터 유지:
      • 데이터베이스와 캐시를 동시에 최신 상태로 유지할 수 있습니다.
    2. 캐시 효율성 유지:
      • 캐시 데이터를 무효화하지 않고, 필요한 데이터를 덮어쓰므로 데이터베이스 호출을 줄일 수 있습니다.
    3. 명시적 업데이트:
      • 특정 데이터에 대한 업데이트만 수행할 수 있어 캐시 효율성이 높습니다.

    단점:

    1. 추가 실행 비용:
      • 메서드가 항상 실행되고 그 결과가 캐시에 저장되므로, 단순한 데이터 조회보다 비용이 높을 수 있습니다.
    2. 데이터 불일치 가능성:
      • 캐시 업데이트가 데이터베이스 상태와 항상 일치하지 않을 수 있습니다(예: 데이터베이스 상태가 외부 요인으로 변경된 경우).

     

    특징 @CacheEvict @CachePut
    사용 목적 더 이상 유효하지 않은
    데이터를 캐시에서 제거.
    항상 실행하여 캐시 데이터를 업데이트.
    적합한 경우 - 데이터가 삭제되었거나 더 이상 사용되지 않을 때. - 데이터가 업데이트되었고, 캐시와 데이터베이스를 동기화해야 할 때.
    캐시 상태 캐시 항목 제거(무효화). 캐시에 새 데이터로 덮어씀.
    성능 고려 캐시를 제거하므로 필요 시 재조회 비용 발생. 캐시 데이터를 유지하므로 데이터베이스 호출 감소 가능.
    주요 단점 재조회 시 데이터베이스 호출이 필요해 성능 저하 가능. 메서드가 항상 실행되므로 필요하지 않을 때에도 비용 발생 가능.

     

     

    캐시 동적 사용

    Spring의 @CacheEvict 어노테이션에서 conditionunless 속성을 사용하면 동적으로 캐시 무효화를 제어할 수 있습니다. 이를 활용하여 특정 조건에서만 캐시를 무효화하거나, 특정 조건에서는 캐시를 유지하도록 구현할 수 있습니다

     

    속성 설명

    1. condition:
      • 캐시 무효화 작업이 수행되기 에 평가됩니다.
      • 표현식이 true를 반환하면 캐시 무효화를 수행하고, false를 반환하면 무효화하지 않습니다.
    2. unless:
      • 캐시 무효화 작업이 수행된 에 평가됩니다.
      • 표현식이 true를 반환하면 무효화 작업을 취소하고, false를 반환하면 무효화를 유지합니다.
    @CacheEvict(value = "products", key = "#id", condition = "#id > 10")
    public void deleteProduct(Long id) {
        productRepository.deleteById(id);
    }
    
    /**
    설명:
        id 값이 10보다 큰 경우에만 캐시에서 항목을 제거합니다.
    
        id <= 10인 경우 캐시는 변경되지 않습니다.
    */

     

    @CacheEvict(value = "products", key = "#id", unless = "#result == null")
    public void deleteProduct(Long id) {
        Product product = productRepository.findById(id).orElse(null);
        if (product != null) {
            productRepository.delete(product);
        }
    }
    
    /**
    설명:
       deleteProduct 메서드 실행 후 반환된 #result가 null이면 캐시를 무효화하지 않습니다.
    
        삭제할 대상이 존재하지 않을 때 캐시를 유지합니다.
    */

     

    @CacheEvict(value = "products", key = "#id", condition = "#id > 10", unless = "#result == null")
    public boolean deleteProduct(Long id) {
        Product product = productRepository.findById(id).orElse(null);
        if (product != null) {
            productRepository.delete(product);
            return true;
        }
        return false;
    }
    
    /**
    설명:
    
        condition: id > 10인 경우에만 캐시 무효화 조건을 진행합니다.
        unless: 메서드 실행 결과가 null이면 캐시를 무효화하지 않습니다.
    
    */

     

    활용 시 주의사항

    1. SpEL 표현식 사용:
      • conditionunlessSpring Expression Language(SpEL)를 사용합니다.
      • 파라미터메서드 결과 값기준으로 조건을 지정해야 합니다.
        • 예: #id, #root.args[0], #result.
    2. 성능 고려:
      • 조건이 너무 복잡하면 캐싱의 성능 이점을 상쇄할 수 있으므로 간단한 조건을 사용하는 것이 좋습니다.
    3. 결과 의존성:
      • unless메서드 결과에 의존하므로, 반환 타입이 적절히 정의되어 있어야 합니다.
      • 반환 값이 없는 경우(void)에서는 사용할 수 없습니다.
    4. 동작 순서:
      • condition은 캐시 무효화 실행 여부를 결정하기 에 평가됩니다.
      • unless는 캐시 무효화가 완료된 후 조건을 평가하여 작업을 취소할 수 있습니다.

    댓글

Designed by Tistory.