안녕하세요.
오늘은 캐시 (Cache) 에 대해 한 번 정리해보려고 합니다.
캐시는 빠르게 서비스를 만들고, 사용자 경험을 지키는 데 중요한 내용입니다.
가장 많이 사용되는 Cache 중 Redis가 있는데요.
보통 편하고 쉽게 성능 좋은 캐시를 쓸 수 있으니, 무조건 Redis를 쓰면 되는 것 아닌가 라는 잘못된 생각하는 경우도 있습니다.
하지만 Cache는 보통 Local Cache와 Remote Cache 가 있고,
언제 어떻게 사용해야 좋을 지가 각 상호아에 따라 모두 다릅니다. 오늘은 그 성격과 특징을 정리해보겠습니다.
■ Local Cache ?
LocalCache는 애플리케이션 인스턴스 안의 메모리에 데이터를 저장하는 방식입니다.
이런 구조 덕분에 DB나 외부 Cache까지 갈 필요 없이, 바로 메모리에서 값을 읽어오기 때문에 매우 빠릅니다.
단점이 있다면 크게 2가지가 있을 것 같습니다.
- 서버가 여러 대일 경우 캐시가 공유되지 않는다
- 서버 재시작 시 캐시가 초기화된다
보통 Java와 Spring 조합 에서 많이 쓰이는 Local Cache는 ehCache와 Caffeine이 있습니다.
이 2가지에 대해서도 간략히 정리해보겠습니다.
1️⃣ ehCache
- 오래된 만큼 안정성과 생태계가 잘 잡혀 있습니다.
- JPA의 2차 캐시와 연동하기에도 편리합니다.
- XML이나 Java Config를 통한 TTL 설정이 가능합니다.
- 참고 : https://www.ehcache.org/documentation/
2️⃣ Caffeine
- Google이 개발한 고성능 캐시 라이브러리입니다.
- ConcurrentHashMap보다도 빠르고 세밀한 설정이 가능해서 실시간 서비스에 적합해요.
- TTL, 용량 기반 제거, 접근 패턴 분석 등 매우 똑똑합니다.
- 참고 : https://github.com/ben-manes/caffeine
■ Remote Cache ?
Remote Cache는 별도의 인메모리 서버에서 동작하는 캐시입니다. 대표적으로 Redis가 있습니다.
서버 간 공유가 가능하고, TTL, 만료 정책, 정렬된 데이터 처리에 매우 강합니다.
다만, 네트워크 비용이 있으므로 Local Cache보다는 느릴 수 있습니다.
■ Local Cache vs Remote Cache 간단 비교
■ ehCache, Caffeine, Redis 설정 예제
그럼 다음은 각 Cache를 어떻게 설정하고 사용하는지 간단한 샘플코드를 통해 정리해보겠습니다.
☑️ ehCache
// build.gradle
implementation 'org.ehcache:ehcache:3.10.8'
// Cache 설정
@Configuration
@EnableCaching
public class EhCacheConfig {
@Bean
public JCacheManagerCustomizer cacheManagerCustomizer() {
return cm -> {
CacheConfiguration<Object, Object> config = CacheConfigurationBuilder
.newCacheConfigurationBuilder(
Object.class, Object.class,
ResourcePoolsBuilder.heap(1000)
)
.withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(10)))
.build();
cm.createCache("userCache", config);
};
}
@Bean
public CacheManager cacheManager(javax.cache.CacheManager jCacheManager) {
return new JCacheCacheManager(jCacheManager);
}
}
// Cache 사용
@Cacheable(value = "userCache", key = "#userId")
public User getUserById(Long userId) {
return userRepository.findById(userId).orElseThrow();
}
☑️ Caffeine
// build.gradle
implementation 'com.github.ben-manes.caffeine:caffeine'
// Cache 설정
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
Caffeine<Object, Object> caffeine = Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.maximumSize(1000);
return new CaffeineCacheManager("userCache", caffeine);
}
}
// Cache 사용
@Cacheable(value = "userCache", key = "#userId")
public User getUserById(Long userId) {
return userRepository.findById(userId).orElseThrow();
}
☑️ Redis
// build.gradle
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
// Cache 설정
@Configuration
@EnableCaching
public class RedisCacheConfig {
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30));
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
}
// Cache 사용
@Cacheable(value = "userCache", key = "#userId")
public User getUser(Long userId) {
return userRepository.findById(userId).orElseThrow();
}
각 캐시 별로 코드 자체가 크게 다르지 않음을 볼 수 있습니다.
캐시를 통해 코드를 개발하고, 설정하는 것 보다는 각 서비스와 데이터 특징에 따라 어떠한 캐시를 사용하는지 결정하는 것이 중요합니다.
이 내용을 바탕으로 실제 언제 어떤 Cache를 써야 할지를 정리하며, 이 글을 마무리 하겠습니다.
■ 언제 어떤 Cache를 써야 할까?
📝 단일 서버이고, 고속 응답이 필요한 경우
-> LocalCache
📝 여러 서버에 Cache 데이터 공유가 필요한 경우
-> RemoteCache
위와 같이 명확한 각 상황에서는 LocalCache와 RemoteCache를 구분하여 사용하는 것이 좋습니다.
하지만 그 외에는 각 상황에 맞는 Cache를 적절하게 선택하여 개발하는 것이 좋습니다.
실제로 서비스 개발 할 때는 보통 LocalCache (ehCache or Caffeine) 와 RemoteCache (Redis)를 함께 사용하는 이중 캐시 전략을 쓰고 있습니다.
글을 간단히 요약하자면 다음과 같습니다.
- 캐시는 성능 개선의 핵심 도구지만, 언제 어디에 어떤 캐시를 쓸지가 더 중요합니다.
- 시스템 구조, 데이터의 생명주기, 동시성, 트래픽 상황 등을 고려해서 적절하게 선택해야 합니다.
- 실제 서비스에서 보통 이중 캐시 전략을 쓰고 있습니다.
그럼 오늘 글을 마치겠습니다. 감사합니다.
'Backend Engineering' 카테고리의 다른 글
[Serverless 서비스 개발] #2. serverless Framework로 Lambda 배포하기 (2) | 2025.06.19 |
---|---|
[Serverless 서비스 개발] #1. 시스템 설계 (1) | 2025.06.18 |
Spring Security를 활용한 인증 흐름 정리 (0) | 2025.06.09 |
OAuth 2.0 개념 정리 (1) | 2025.06.05 |
JWT(Json Web Token) 간단 정리 (0) | 2025.06.02 |