Spring Cache에서 @Cacheable, @CachePut, @CacheEvict의 차이점과 각각을 어떤 상황에서 사용하는 것이 적절한지 설명해주세요.
1. @Cacheable
설명 : 메서드 실행 결과를 캐시에 저장하고, 동일한 인자로 호출 시 저장된 값을 반환하여 조회 성능을 향상시키기 위해 사용
- @Cacheable("products") → 캐시 이름이 products인 저장소에 결과를 저장
- 동일한 ID로 다시 호출되면 DB 접근 없이 캐시된 결과를 반환
- condition 과 unless 속성을 이용하면 캐시 조건을 제어할 수 있음
| 속성 | 설명 |
| condition | 캐싱을 수행할 조건 지정 (true일 때만 저장) |
| unless | 메서드 실행 후 결과에 따라 저장 여부 결정 |
@Service
public class ProductService {
@Cacheable(value = "products", condition = "#id > 0", unless = "#result == null")
public Product findProductById(Long id) {
System.out.println("DB 접근 발생!");
return new Product(id, "노트북", 1200000);
}
}
2. @CachePut
설명 : 항상 메서드를 실행하고, 실행 결과를 캐시에 강제로 갱신하여 데이터 갱신 후 캐시 동기화를 위해 사용
- condition 과 unless 외에 key 속성을 사용
| 속성 | 설명 |
| key | 캐시 키를 SpEL로 지정. 지정하지 않으면 기본 키 생성 규칙(모든 파라미터 기반)이 사용 |
@Service
public class ProductService {
@CachePut(value = "products", key = "#product.id")
public Product updateProduct(Product product) {
System.out.println("DB에서 제품 업데이트 후 캐시 갱신");
return product;
}
}
3. @CacheEvict
설명 : 캐시된 데이터를 제거할 때 사용
- beforeInvocation 과 allEntries 속성을 사용하여 삭제 조건을 제어할 수 있음
| 속성 | 설명 |
| beforeInvocation | 메서드를 실행하기 전에 캐시를 삭제하도록 지정(기본값은 false로 메서드 실행 후 삭제) |
| allEntries | 모든 캐시를 삭제하도록 지정 |
@Service
public class ProductService {
@CacheEvict(value = "products", key = "#id")
public void deleteProduct(Long id) {
System.out.println("DB에서 제품 삭제 후 캐시 제거");
}
}
//전체 캐시 삭제
@CacheEvict(value = "products", allEntries = true)
public void clearCache() {
System.out.println("모든 캐시 제거");
}
나만의 언어로 정리해보기
Spring Cache
@Cacheable
- 메서드 실행 결과를 캐시에 저장하고, 동일한 인자로 호출 시 저장된 값을 반환하여 조회 성능을 향상 시키기 위해 사용
@CachePut
- 항상 메서드를 실행하고, 실행 결과를 캐시에 강제로 갱신하여 데이터 갱신 후 캐시 동기화를 위해 사용
@CacheEvict
- 캐시된 데이터를 제거할 때 사용
로컬 캐시와 분산 캐시의 개념 차이와 각각의 장단점, 그리고 실무에서 어떤 기준으로 선택해야 하는지 설명해주세요.
1. 로컬 캐시(In-Memory Cache)
1. 개념
- 애플리케이션 내부 메모리(RAM) 에 데이터를 저장하는 캐시 구조
- 서버 자체에 존재하므로 외부 네트워크 요청 없이 가장 빠르게 데이터에 접근할 수 있음
- 장점
- 네트워크 호출이 없어 응답 속도가 가장 빠릅니다.
- 단순 구현 가능 (HashMap, Caffeine 등)
- 외부 장애(네트워크, Redis 다운 등)에 영향받지 않습니다.
- 단점
- 서버마다 캐시가 달라 데이터 불일치 가능성이 있습니다.
- 서버 재시작 시 캐시가 모두 초기화됩니다.
- 확장성(Scalability)이 낮습니다.
| 항목 | 설명 |
| 속도 | 매우 빠름(메모리 직접 접근) |
| 범위 | 서버 프로세스 내부에서만 사용 가능 |
| 일관성 | 서버간 공유 불가 → 데이터 불일치 발생 가능 |
| 운영 난이도 | 낮음(별도 서버 없음) |
2. 분산 캐시(Distributed Cache)
1. 개념
- 여러 서버 인스턴스가 동일한 캐시 서버를 공유하는 구조
- 일반적으로 Redis, Memcached 같은 인메모리 서버를 사용
- 여러 서버가 하나의 중앙 캐시 저장소를 공유
- 데이터 일관성 유지가 용이하며, 확장성(Scale-out)에 유리
- 장점
- 여러 서버 간 데이터 공유 가능.
- 캐시 서버 장애 시에도 Persistence(데이터 영속화) 설정 가능.
- 수평 확장(Scale-Out) 에 유리함.
- 단점
- 네트워크 지연이 존재합니다.
- Redis 장애 시 모든 요청이 DB로 몰릴 수 있습니다.
- 운영/모니터링 복잡도가 증가합니다.
| 항목 | 설명 |
| 속도 | 빠름 (네트워크 접근 존재) |
| 데이터 일관성 | 모든 서버가 동일 캐시 사용 → 높은 일관성 |
| 확장성 | 높음 (노드 추가 가능) |
| 운영 복잡도 | Redis/Memcached 서버 운영 필요 |
3. 로컬 캐시와 분산 캐시의 실무 선택 기준
| 기준 | 로컬 캐시 | 분산 캐시 |
| 속도 | 매우 빠름 (네트워크 없음) | 네트워크 왕복 있음 (수 ms) |
| 일관성 | 낮음 (인스턴스별 불일치 가능) | 높음 (모든 인스턴스 공유) |
| 확장성 | 서버 수 증가 시 히트율 ↓ | 수평 확장에 유리 |
| 데이터 크기 | 인스턴스 메모리 한정 | 큰 데이터도 저장 가능 |
| 운영 복잡도 | 단순 (별도 서버 X) | 인프라 필요 (Redis 등 운영) |
| 주요 사용처 | 설정값, 권한, 자주 읽는 소형 데이터 | 세션, 랭킹, 토큰, 대용량 캐시 |
| 일관성 요구 | 약한 경우 적합 | 강한 경우 필수 |
| 장애 영향 | 서버 재시작 시 캐시 초기화 | 재시작에도 캐시 유지 가능 |
- 속도와 간결성이 우선 → 로컬 캐시
- 여러 인스턴스 간 공유와 일관성이 중요 → 분산 캐시
나만의 언어로 정리해보기
로컬 캐시와 분산 캐시
로컬 캐시
- 애플리케이션 내부 메모리에 데이터를 저장하는 캐시 구조로, 서버 자체에 존재하므로 외부 네트워크 요청 없이 가장 빠르게 데이터에 접근할 수 있다.
- 장점
- 외부 장애에 영향을 받지 않으며 단순 구현이 가능하고 응답 속도가 가장 빠르다.
- 단점
- 확장성이 낮고 서버 재시작 시 캐시가 모두 초기화되며, 서버마다 캐시가 달라 데이터 불일치의 가능성이 있다.
분산 캐시
- 여러 서버 인스턴스가 동일한 캐시 서버를 공유하는 구조로, 일반적으로 Redis, Memcached 같은 인메모리 서버를 사용한다.
- 여러 서버가 하나의 중앙 캐시 저장소를 공유하고, 데이터 일관성 유지가 용이하며, 확장성에 유리하다.
- 장점
- 여러 서버 간 데이터 공유가 가능하고, 캐시 서버 장애 시에도 데이터 영속화 설정이 가능하며 수평 확장에 유리하다.
- 단점
- 네트워크 지연이 존재하고, Redis 장애 시 모든 요청이 DB로 몰릴 수 있으며 운영/모니터링 복잡도가 증가한다.
로컬 캐시와 분산 캐시의 실무 선택 기준
- 속도와 간결성이 우선되면 로컬 캐시
- 여러 인스턴스 간 공유와 일관성이 중요하면 분산 캐시
'코드잇 BE스프린트' 카테고리의 다른 글
| 위클리 페이퍼 - 17주차 (1) | 2026.05.04 |
|---|---|
| 위클리 페이퍼 - 15주차 (0) | 2026.05.01 |
| 위클리 페이퍼 - 14주차 (0) | 2026.04.30 |
| 위클리 페이퍼 - 13주차 (0) | 2026.04.29 |
| 위클리 페이퍼 - 12주차 (0) | 2026.04.29 |