Backend Engineering

[Cache] Local Cache vs Redis, 언제 어떤 캐시를 써야 할까?

zamezzz 2025. 6. 16. 15:02

안녕하세요.

오늘은 캐시 (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)를 함께 사용하는 이중 캐시 전략을 쓰고 있습니다.

 

글을 간단히 요약하자면 다음과 같습니다.

  • 캐시는 성능 개선의 핵심 도구지만, 언제 어디에 어떤 캐시를 쓸지가 더 중요합니다.
  • 시스템 구조, 데이터의 생명주기, 동시성, 트래픽 상황 등을 고려해서 적절하게 선택해야 합니다.
  • 실제 서비스에서 보통 이중 캐시 전략을 쓰고 있습니다.

 

그럼 오늘 글을 마치겠습니다. 감사합니다.