@Cacheable 동작 원리 사용법 만료시간 unless value example
@Cacheable의 핵심 동작 원리와 내부 메커니즘
Spring의 @Cacheable은 AOP(Aspect Oriented Programming)를 기반으로 동작합니다. 클라이언트가 메서드를 호출하면 프록시 객체가 이를 가로채어 캐시 저장소에서 데이터를 먼저 조회합니다.
캐시 히트(Cache Hit): 저장된 키(Key)가 존재하면 메서드 본문을 실행하지 않고 즉시 값을 반환합니다.
캐시 미스(Cache Miss): 저장된 데이터가 없으면 실제 메서드를 실행한 뒤, 그 결과값을 캐시에 저장하고 반환합니다.
2026년 현재 고성능 백엔드 설계에서는 단순 로컬 캐싱을 넘어 Redis나 Caffeine과 같은 외부 캐시 솔루션을 결합하여 네트워크 지연과 DB 부하를 동시에 관리하는 것이 표준입니다.
@Cacheable 주요 속성 및 사용법
효율적인 캐싱 전략을 위해서는 각 속성의 역할을 정확히 이해해야 합니다.
value (또는 cacheNames): 캐시의 이름을 지정합니다. (예:
specialHoliday)key: 캐시 저장 시 사용할 키를 지정합니다. 지정하지 않으면 파라미터 기반으로 자동 생성됩니다.
unless: 특정 조건일 때만 캐시에 저장하지 않도록 설정합니다. (결과값이 null이거나 특정 상태일 때 유용)
condition: 메서드 실행 전에 캐시 적용 여부를 결정합니다.
구체적인 코드 활용 예시 (unless, condition 포함)
단순 조회를 넘어 실무에서 자주 발생하는 특정 상황(결과가 비어있을 경우 제외 등)을 처리하는 예시 코드입니다.
@Override
@Cacheable(
value = "specialHoliday",
key = "#year",
unless = "#result == null || #result.isEmpty()"
)
public List<SpecialHoliday> getCacheSpecialHolidayList(String year) {
// 결과가 null이거나 비어있는 리스트라면 캐싱하지 않음
return etcDao.selectCacheSpecialHolidayList(year);
}
💡 주요 옵션 상세 설명
| 옵션 | 설명 | 예시 |
| value | 저장될 캐시 영역의 이름 | value = "holiday" |
| unless | 메서드 실행 후 결과에 따른 캐싱 방지 | unless = "#result == null" |
| condition | 메서드 실행 전 입력 값에 따른 캐싱 여부 | condition = "#year.length() == 4" |
캐시 만료 시간(TTL) 및 정합성 관리
@Cacheable 자체에는 만료 시간을 직접 설정하는 속성이 없습니다. 2026년 기준 표준 방식은 사용 중인 CacheManager 설정을 통해 TTL(Time To Live)을 제어하는 것입니다.
Redis 설정:
RedisCacheConfiguration을 통해 각 캐시 이름별로 다른 TTL을 적용합니다.Caffeine(로컬):
CaffeineCacheManager설정에서expireAfterWrite를 사용하여 시간 기반 만료를 설정합니다.데이터 정합성: 데이터가 업데이트되는 시점에는
@CacheEvict를 호출하여 반드시 기존 캐시를 삭제하거나@CachePut으로 갱신해야 합니다.
자주 묻는 질문 (FAQ)
Q1. @Cacheable을 적용했는데 왜 DB 쿼리가 계속 나갈까요?
동일 클래스 내에서 내부 호출(Self-invocation)을 한 경우 AOP 프록시가 작동하지 않습니다. 반드시 외부 Bean에서 호출하거나 구조를 분리해야 캐싱이 적용됩니다. 또한 @EnableCaching 설정이 누락되었는지 확인하십시오.
Q2. unless와 condition의 차이점은 무엇인가요?
condition은 메서드 실행 전에 파라미터를 기준으로 캐싱 여부를 판단하고, unless는 메서드 실행 후 결과값(#result)을 보고 캐시 저장 여부를 결정합니다. 결과가 null일 때 캐싱을 피하려면 unless를 사용해야 합니다.
Q3. 캐시 만료 시간을 어노테이션에서 직접 조절할 수 없나요?
Spring 표준 어노테이션에서는 지원하지 않습니다. 이는 캐시 공급자(Redis, Ehcache 등)의 독립성을 유지하기 위함입니다. 각 캐시 솔루션의 Configuration 클래스에서 Bean 설정을 통해 관리하는 것이 올바른 아키텍처입니다.
Q4. 여러 개의 파라미터 중 특정 값만 키로 사용하고 싶다면 어떻게 하나요?
key = "#paramName" 형식을 사용하면 됩니다. 만약 여러 파라미터를 조합해야 한다면 key = "#p0 + '_' + #p1" 처럼 SpEL(Spring Expression Language)을 활용하여 커스텀 키를 생성할 수 있습니다.
@Cacheable 핵심 요약
프록시 기반 동작: 내부 호출 시 캐시가 작동하지 않으므로 주의가 필요합니다.
조건부 캐싱:
unless와condition을 적절히 혼합하여 불필요한 데이터(null 등)가 메모리를 점유하지 않도록 설계합니다.만료 전략: TTL은 CacheManager 설정에서 전역 또는 이름별로 관리하며, 데이터 수정 시
@CacheEvict로 정합성을 맞추는 것이 필수입니다.
댓글
댓글 쓰기