Spring

[Spring] Spring Cache에서 @Cacheable, @CachePut, @CacheEvict의 차이점과 적절한 사용법

leejunkim 2025. 10. 20. 10:51

WeeklyPaper: Spring Cache에서 @Cacheable, @CachePut, @CacheEvict의 차이점과 각각을 어떤 상황에서 사용하는 것이 적절한지 설명해주세요.


스프링에서는 스프링 AOP 기반으로 캐시가 장독하여 어노테이션으로 AOP를 설정할 수 있어서 간편하게 사용할 수 있다. 주로 사용되는 어노테이션은 @Cacheable, @CachePut, @CacheEvict다.

 

build.gradle에 추가하자:

implementation 'org.springframework.boot:spring-boot-starter-cache'

 

@Cacheable

캐시 생성과 전달을 담당한다.

메서드가 호출 될때마다 이 메서드는 이미 호출이 되었는지 확인하기 위해 캐시가 확인된다.

  • 캐시에 데이터가 없을 경우, 기존의 로직을 실행 후 캐시에 데이터를 추가한다.
  • 캐시에 데이터가 있을 경우, 메서드는 호출되지 않고 캐시의 데이터만 반환한다.
// 캐시 저장
@Cacheable("userCacheStore")
public User cacheable(String date) {
	System.out.println("cacheable 실행");
    return User;
}

// 캐시 저장 (key를 지정한 경우)
@Cacheable(value="userCacheStore", key = "#user.name")
public User cacheableByKey(User user) {
	System.out.println("cacheable 실행");
    return User;
}

//조건부 캐시 실행 (with condition)
@Cacheable(value = "userCacheStore", key = "#user.name", condition = "#user.name.length() > 5")
public User cacheableByKey(User user) {
	System.out.println("cacheableWithCondition 실행");
    return User;
}
  1. @Cacheable("userCacheStore")
    • key없이 캐시 저장
    • 처음으로 메서드가 호출될 경우, "cacheable 실행" 문자열이 출력되고 반환값인 User은 개시 저장소에 저장된다.
    • 그 다음 모든 메서드 호출은 캐시 저장소에 저장된 User 값이 반환되고, 문자열은 출력되지 않는다.
  2. @Cacheable(value="userCacheStore", key = "#user.name") 
    • key를 사용해서 캐시 저장
    • 처음으로 특정 name값을 가진 유저가 들어올때는 "cachable 실행" 문자열이 출력되고 그 이름을 가진 유저 객체 데이터는 캐싱된다.
    • 같은 이름을 가진 유저 객체로 다시 메서드를 호출하면 캐싱된 유저 데이터 객체다 반환되고, "cachable 실행" 문자열은 출력되지 않는다.
  3. @Cacheable(value = "userCacheStore", key = "#user.name", condition = "#user.name.length() > 5") 
    • 조건부 캐싱 - @Cachable 어노테이션에 condition 속성을 추가해서 사용 가능하다.

@CachePut

캐시 수정 내용을 담당한다. @Cacheable과 유사하게 실행 결과를 캐시에 저장하지만, 조회 시 저장된 캐시 내용을 사용하지 하노고 항상 메서드를 실행한다.

@CachePut(value="userCacheStore", key="#user.name")
public User cachePut(User user) {
	System.out.println("cachePut 실행");
    return User;
}
  • 메서드 실행에 영향을 주지 않고 캐시를 갱신해야되는 경우에만 사용된다.
  • @Cacheable와 같은 option들을 사용하면 된다.

@CacheEvict

캐시 삭제를 담당한다.

// 캐시 제거
@CacheEvict("userCacheStore")
public User cacheEvict(String date) {
	System.out.println("cacheEvict 실행");
    ...
    return User;
}

// name 키 값을 가진 캐시만 제거
@CacheEvict("userCacheStore", key="#user.name")
public User cacheEvictByKey(User user) {
	System.out.println("cacheEvictByKey 실행");
    ...
    return User;
}

// 캐시에 저장된 값을 모두 제거
@CacheEvict("userCacheStore", allEntries = true)
public User cacheEvictAllEntries() {
	System.out.println("cacheEvictAllEntries 실행");
    ...
    return User;
}

@CacheEvict(value="userCacheStore", beforeInvocation = true) 
public User cacheEvictBeforeInvocation() {
    System.out.println("cacheEvictBeforeInvocation 실행");
    ...
    return User;
}

 

  1. @CacheEvict("userCacheStore") - 기본
    • userCacheStore라는 이름의 캐시에서 특정 항목 하나만 제거한다. 어떤 항목을 지울지는 메서드의 매개변수를 기반으로 결정된다. 
    • cacheEvict(String date) 메서드가 호출될 때, 만약 date 값이 "2025-10-20"이라면, "userCacheStore" 캐시에서 "2025-10-20"이라는 키(key)를 가진 항목을 찾아 삭제한다.
  2. @CacheEvict("userCacheStore", key="#user.name")
    • 매개변수의 이름이 키로 사용되는 객체 데이터가 캐시 안에 저장되어있다면 삭제된다.
  3. @CacheEvict("userCacheStore", allEntries = true)
    • 모든 항목을 한 번에 제거한다. (그냥 캐시 전체를 비운다)
  4. @CacheEvict(value="userCacheStore", beforeInvocation = true) 
    • 메서드 로직이 실행되기 전에 혹은 후에 캐시를 삭제할지 결정한다
      • 예) beforeInvocation = true 옵션은 메서드 로직이 실행되기 전에 캐시를 먼저 삭제한다.
    • 기본값은 false이며, 이때는 메서드가 성공적으로 완료된 후에 캐시를 삭제한다. (즉, 메서드 실행 중 예외가 발생하면 캐시가 삭제되지 않는다.)

 

자료