@Component
@RefreshScope
@ConfigurationProperties("cache")
class CacheProperties {
var ttlByNames: Map<String, Duration> = emptyMap()
}
서버에서 캐시를 활용할 때 TTL을 동적으로 지정하기 위해 위와 같이 TTL을 환경변수로 관리하고 있었습니다.
셀러(상품 공급자)에게 공지사항을 보여줄 때 사용할 캐시를 하나 만들었고, 이름은 sellerNotice
으로 지정했습니다.
쿠버네티스 환경에 서버가 배포되기 때문에 Argocd로 환경변수를 관리하고 있었고, 다음과 같은 설정으로 TTL이 주입되기를 기대했습니다.
- key: CACHE_TTLBYNAMES_SELLERNOTICE
value: 12h
그런데 실제로 환경변수 설정이 주입되지 않아 서버 내부적으로 가지고 있는 기본 TTL 1시간이 설정된 것이 확인되었습니다.
실제로 ttl이 어떻게 주입되는지 로그를 찍어서 확인해봤습니다.
ttlByNames={sellernotice=PT12H}
Map의 key가 제가 원하는 "sellerNotice"의 형태가 아닌 "sellernotice"의 형태로 주입이 되고 있었습니다.
이유는 spring boot의 relaxed binding rule 때문이었습니다. enum이나 변수명 같이 컴파일 시점부터 런타임 시점까지 대소문자가 정해져 있는 경우에는 주입이 잘 되지만 Map의 key와 같이 어떤 문자인지 정해져 있지 않은 경우에는 relaxed binding rule이 적용되어 주입되는 것을 확인했습니다.
따라서, argocd에서 작성해서 주입하면 쿠버네티스 환경에 있는 애플리케이션에는 다음과 같이 들어가게 됩니다.
이로 인해 SELLERNOTICE
라는 Map의 key 값이 모두 소문자로 변환되어 "sellernotice"로 주입되어 실제 애플리케이션의 캐시 이름과 이격이 발생해 TTL 기본값이 적용되었습니다.
application.yaml
파일이나 spring cloud config의 yaml 파일에서는 대소문자 및 _ 등도 모두 그대로 주입될 수 있으니 동적인 환경변수 주입이 필요하다면 spring cloud config를 사용하는 것이 좋다.