Relaxed binding rule

신연우·2023년 12월 2일
0

WIL

목록 보기
11/13

배경

@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 기본값이 적용되었습니다.

인사이트

  • 외부에서 환경변수를 주입할 때 Map의 key가 String 타입이라면 Relaxed binding rule에 의해 원하는대로 값이 주입되지 않을 수 있으니 테스트가 필요하다.
  • 서버의 application.yaml 파일이나 spring cloud config의 yaml 파일에서는 대소문자 및 _ 등도 모두 그대로 주입될 수 있으니 동적인 환경변수 주입이 필요하다면 spring cloud config를 사용하는 것이 좋다.

참고한 글

profile
남들과 함께하기 위해서는 혼자 나아갈 수 있는 힘이 있어야 한다.

0개의 댓글