Files
llm-wiki/wiki/concepts/config-and-adapter-templates.md

9.9 KiB

title, source_type, status, confidence, tags, related_projects, last_reviewed
title source_type status confidence tags related_projects last_reviewed
Config & Adapter Templates (env-driven + optional module) llm-generated draft medium
12-factor
config
spring-boot
adapter
conditional-on-property
ca-skeleton
2026-05-22

Config & Adapter Templates (env-driven + optional module)

Layer: wiki/concepts/ — env 기반 runtime configuration과 optional adapter template를 동시에 다루는 일반 개념 문서. 구체적인 프로젝트 결정은 raw/project-notes/ca-skeleton-operational-contract §9 및 raw/branch-notes/feature-env-driven-runtime-configuration, raw/branch-notes/feature-integration-adapter-templates 참조.

Summary

Env config: 12-factor §III. Config 원칙을 따라 application-owned env에 APP_ prefix, Duration은 30s 형식 1택, boolean은 true/false only, runtime reload는 기본 금지, .env.example drift 검증 도구로 누락 감지를 강제하는 설계.

Adapter templates: 선택형 adapter(Kafka/Redis/Slack/Email)는 기본 dependency가 아닌 optional module로 두고, @ConditionalOnProperty 3-layer(Layer 1 Spring bean 등록 조건, Layer 2 ArchUnit static dependency 검사, Layer 3 runtime AdapterDisabledException fail-fast)로 disabled adapter가 use case path에 새지 않게 막는 설계.

Standard (공식 정의)

Env-driven runtime configuration

  • 12-factor §III. Config — config는 코드와 분리된 환경 변수에 두고, 배포 환경별로 달라지는 값(자격 증명, hostname, profile)은 모두 env로 주입. config dump가 가능하면 안 됨.
  • Spring Boot externalized configuration@ConfigurationProperties + @Validated로 env 바인딩, application.yml profile-specific override, Spring Duration (30s/PT30S) / DataSize (10MB) 타입 지원.
  • 검토된 대안:
    • Spring Cloud Config Server — 중앙 git-backed config + @RefreshScope로 runtime reload. config server 자체가 인프라 SPOF가 되고 bootstrap에 의존.
    • k8s ConfigMap + Spring Cloud Kubernetes auto-reload — 3-level reload (refresh / restart_context / shutdown).
    • HashiCorp Consul KV — KV store + watch.
    • AWS Parameter Store / AppConfig — managed validator + CloudWatch auto-rollback + deployment strategy.
    • LaunchDarkly / Unleash — feature flag SaaS. A/B/canary, user-targeting, percentage rollout 등 product-grade 기능 제공.

Adapter templates (optional module)

  • Spring @ConditionalOnPropertyname/havingValue 조건이 일치할 때만 bean 등록. Spring Boot 3.5.0+에서 @ConditionalOnBooleanProperty 도입.
  • Spring Boot AutoConfigurationMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports에 등록된 @AutoConfiguration 클래스가 조건부 bean을 제공. custom starter의 표준 방식.
  • 검토된 대안:
    • Java SPI / ServiceLoaderMETA-INF/services/<interface>에 구현체 등록, classpath에서 발견된 모든 provider를 load.
    • Spring @Profile 기반 — profile 활성화로 bean 선택.
    • OSGi plugin architecture — runtime module 동적 load/unload.
    • Feature flag library (FF4J / Togglz) — runtime flag로 코드 path 분기.

한계 / 주의점

Env config

  • 12-factor env (process env 노출) — secret이 process env에 남아 /proc/<pid>/environ, container metadata API, env actuator endpoint로 leak 가능. secret manager 별도 필요.
  • Spring Cloud Config Server — 인프라 SPOF. config server 장애 시 client startup 차단 (bootstrap 의존).
  • k8s ConfigMap auto-reload — pod별로 reload 타이밍이 다르면 partial-state가 생겨 디버깅 어려움. k8s lock-in 발생.
  • AWS AppConfig — AWS lock-in + per-call billing.
  • LaunchDarkly / Unleash — 외부 SaaS 의존, flag debt(제거되지 않은 flag 누적), cost. product-grade A/B/canary 요구가 발생하기 전에는 over-engineering.

Adapter templates

  • Spring @ConditionalOnProperty Layer 1 — Spring 공식이 cover하는 영역은 bean 등록 조건뿐. application code가 disabled adapter package를 import해도 Spring 자체는 막지 못함.
  • ArchUnit Layer 2 — 별도 source가 필요한 미흡 영역. noClasses().that().resideInAPackage("..application..").should().dependOnClassesThat().resideInAPackage("..adapters.{disabled}..") 같은 정적 rule을 작성해야 하며, ca-tmpl 자체 contract로 G-I 후속 보강 대상.
  • ArchUnit Layer 2 정적 검사 한계 (2026-05-22 보강) — ArchUnit User Guide의 DescribedPredicate / ArchCondition API와 JavaClass.getAnnotationOfType(...)로 정적 추출 가능한 것은 (a) adapter 후보 class가 @ConditionalOnProperty를 부착했는지, (b) name/havingValue parameter 값이 app.adapter.<name>.enabled 패턴을 따르는지, (c) application layer가 adapter package를 직접 import하지 않는지(CA 경계)까지. "현재 빌드/배포 환경에서 어떤 adapter가 실제 disabled인지"는 runtime config 평가이므로 ArchUnit 능력 밖이며, Layer 3 (AdapterDisabledException runtime fail-fast)에 위임해야 함. 즉 Layer 2는 "annotation 존재 + naming pattern 강제" fitness function까지가 실효 범위. 자세한 평가는 raw/official-docs/archunit-conditional-on-property-3-layer-pattern 참조. status needs-confirmation.
  • AdapterDisabledException Layer 3 — branch 자체 contract. 표준 라이브러리가 제공하지 않으며 직접 구현.
  • Java SPI — on/off boolean 표현 불가(classpath 존재 = enable), default constructor 강제, Spring DI 미통합. ca-tmpl의 APP_ADAPTER_*_ENABLED 결정과 정면 충돌.
  • Togglz / FF4J — runtime branching tool로, startup-time adapter on/off와 시맨틱이 다름. ca-tmpl @ConditionalOnProperty(startup 결정)와 feature flag service(runtime 결정)는 분리 영역으로 취급해야 함.

Project Application

Interview Questions

  • 12-factor §III. Config가 의미하는 "config와 코드 분리"는 구체적으로 무엇을 강제하는지 설명해 주세요.
  • runtime config reload를 기본 금지(no-runtime-reload)로 결정한 근거와, 그 결정이 운영에서 갖는 trade-off는 무엇인가요?
  • @ConditionalOnProperty 3-layer 검출(Spring bean 조건 + ArchUnit static + runtime fail-fast)이 각각 어떤 실패 시나리오를 잡아내려는 것인지 설명해 주세요.
  • Java SPI ServiceLoader와 Spring @ConditionalOnProperty는 adapter on/off 표현에서 어떤 차이가 있나요?
  • LaunchDarkly 같은 feature flag SaaS와 @ConditionalOnProperty 기반 startup toggle은 어떤 운영 요구가 생겼을 때 갈라지는지 설명해 주세요.

Do Not Overclaim

  • "@RefreshScope만 도입하면 dynamic config가 된다" 같은 단정은 피해야 함. ca-tmpl은 runtime reload를 기본 금지로 두며, reload가 필요한 경우는 secret manager + startup validation을 별도 branch로 분리하는 것이 결정 사항.
  • "@ConditionalOnProperty 3-layer가 disabled adapter 호출을 완전 검증한다"고 단정하면 안 됨. Layer 1만 Spring 공식 cover이고, Layer 2(ArchUnit)는 source 부재로 G-I 후속 보강 대상, Layer 3(AdapterDisabledException)는 branch 자체 contract.
  • "12-factor env가 secret 관리까지 책임진다"는 표현은 과장. process env 노출 위험은 12-factor 자체가 해결하지 않으며 secret manager가 별도 책임.
  • "ca-tmpl이 LaunchDarkly/Togglz를 거부했다"가 아니라 "ca-tmpl scope에서 위임한 영역"이라는 표현이 정확.

Sources