Spring Boot 배포 중 Stale Data 방지를 위한 Redis 캐시 키 버전 관리

발행: (2026년 1월 3일 오전 06:56 GMT+9)
4 min read
원문: Dev.to

Source: Dev.to

애플리케이션은 종종 런타임에 나중에 사용될 컨텐츠를 생성합니다. 이 컨텐츠는 파일 시스템에 저장되거나, 데이터베이스 테이블에 기록되거나, 메시지 브로커를 통해 공유되거나, 공유 캐시에 배치될 수 있습니다. 소프트웨어 시스템은 시간이 지나면서 진화하기 때문에, 이전에 생성된 컨텐츠의 소비자는 이러한 변화를 처리할 수 있어야 하지만, 항상 가능한 것은 아닙니다.

버전 관리가 없는 예시

@Service
public class UserProfileService {
    private final UserRepository userRepository;

    public UserProfileService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Cacheable("userProfile")
    public UserProfile getProfile(Long userId) {
        User user = userRepository.findById(userId).orElseThrow();
        return new UserProfile(
                user.getId(),
                user.getFirstName(),
                user.getLastName()
        );
    }
}

나중에 UserProfileemail 필드를 추가합니다:

return new UserProfile(
        user.getId(),
        user.getFirstName(),
        user.getLastName(),
        user.getEmail()
);

Spring이 이전 객체 구조의 인스턴스로 이미 캐시를 채워두었기 때문에, 이후 getProfile() 호출은 역직렬화 오류와 함께 실패합니다. 예:

org.springframework.data.redis.serializer.SerializationException: Cannot serialize

구체적인 메시지는 직렬화 설정에 따라 달라집니다.

버전 관리가 필요한 이유

문제와 해결책 자체는 개념적으로 단순하지만, 실제 운영 환경에서는 그 영향이 심각할 수 있습니다. 오류는 장시간 다운타임, 배포 실패, 혹은 강제 롤백을 초래할 수 있으며, 특히 캐시 엔트리의 TTL이 길 경우 더욱 그렇습니다.

버전이 포함된 캐시 키

공유 캐시를 사용할 때는 애플리케이션 이름과 함께 버전 식별자를 캐시 키에 포함시키는 것이 일반적이고 효과적인 방법입니다. 이렇게 하면 새로운 애플리케이션 버전이 이전 버전이 만든 호환되지 않는 캐시 데이터를 읽으려 하지 않게 됩니다.

@Configuration
public class CacheConfiguration {

    @Bean
    public RedisCacheConfiguration redisCacheConfiguration(
            ObjectProvider<BuildProperties> buildPropertiesProvider) {

        BuildProperties buildProperties = buildPropertiesProvider.getIfAvailable();

        String name = (buildProperties != null) ? buildProperties.getName() : "application";
        String version = (buildProperties != null) ? buildProperties.getVersion() : "dev";

        return RedisCacheConfiguration.defaultCacheConfig()
                .prefixCacheNameWith(String.format("%s:%s:", name, version));
    }
}

캐시 키는 Maven(리소스 필터링이나 spring-boot-maven-pluginbuild-info 목표 사용), Git 커밋 해시(git-commit-id-plugin 활용) 혹은 CI/CD 파이프라인에서 주입되는 기타 메타데이터를 이용해 구성할 수 있습니다.

결과 Redis 키

위와 같이 전역 키 접두사를 설정하면, 캐시된 엔트리는 버전이 포함된 키로 저장됩니다. 예시:

127.0.0.1:6379> keys *
1) "payment-gateway:1.1.0:userProfile::1"
2) "payment-gateway:1.1.1:userProfile::1"

각 애플리케이션 인스턴스는 자신과 동일한 버전의 캐시 키만 접근하므로, 배포 및 롤백 시 호환되지 않는 캐시 데이터로 인한 역직렬화 오류 없이 안전하게 수행할 수 있습니다.

참고 자료

  • Cache Key Versioning Code Example
  • Add Build Properties to a Spring Boot Application
  • Injecting Git Information Into Spring
  • Spring Data Redis Configuration
Back to Blog

관련 글

더 보기 »

분리를 분리하자

소개 2025년 말 며칠 동안, 우리 팀 리더는 하루를 추가로 쉬면서 중요한 회의를 놓쳤습니다. 최근 구조조정 이후, 한 동료가 떠났습니다.