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 |
|
|
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.ymlprofile-specific override, SpringDuration(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 기능 제공.
- Spring Cloud Config Server — 중앙 git-backed config +
Adapter templates (optional module)
- Spring
@ConditionalOnProperty—name/havingValue조건이 일치할 때만 bean 등록. Spring Boot 3.5.0+에서@ConditionalOnBooleanProperty도입. - Spring Boot AutoConfiguration —
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports에 등록된@AutoConfiguration클래스가 조건부 bean을 제공. custom starter의 표준 방식. - 검토된 대안:
- Java SPI /
ServiceLoader—META-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 분기.
- Java SPI /
한계 / 주의점
Env config
- 12-factor env (process env 노출) — secret이 process env에 남아
/proc/<pid>/environ, container metadata API,envactuator 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
@ConditionalOnPropertyLayer 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/ArchConditionAPI와JavaClass.getAnnotationOfType(...)로 정적 추출 가능한 것은 (a) adapter 후보 class가@ConditionalOnProperty를 부착했는지, (b)name/havingValueparameter 값이app.adapter.<name>.enabled패턴을 따르는지, (c) application layer가 adapter package를 직접 import하지 않는지(CA 경계)까지. "현재 빌드/배포 환경에서 어떤 adapter가 실제 disabled인지"는 runtime config 평가이므로 ArchUnit 능력 밖이며, Layer 3 (AdapterDisabledExceptionruntime fail-fast)에 위임해야 함. 즉 Layer 2는 "annotation 존재 + naming pattern 강제" fitness function까지가 실효 범위. 자세한 평가는 raw/official-docs/archunit-conditional-on-property-3-layer-pattern 참조. statusneeds-confirmation. AdapterDisabledExceptionLayer 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
- wiki/projects/ca-tmpl/config-and-adapter-templates — ca-tmpl 의사결정 기록 (현재
documented-only, Phase C2 미진입). 실제 구현 여부는 project 문서 참조. - raw/branch-notes/feature-env-driven-runtime-configuration —
APP_prefix, Duration30s, booleantrue/false, no-runtime-reload,.env.exampledrift 검증 결정. - raw/branch-notes/feature-integration-adapter-templates — optional module +
@ConditionalOnProperty3-layer detection +AdapterDisabledExceptionfail-fast 결정. - raw/project-notes/ca-skeleton-operational-contract — §9 Env-driven Runtime Configuration, §11 Adapter Failure Contract, §29 Group G-I.
Interview Questions
- 12-factor §III. Config가 의미하는 "config와 코드 분리"는 구체적으로 무엇을 강제하는지 설명해 주세요.
- runtime config reload를 기본 금지(no-runtime-reload)로 결정한 근거와, 그 결정이 운영에서 갖는 trade-off는 무엇인가요?
@ConditionalOnProperty3-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로 분리하는 것이 결정 사항. - "
@ConditionalOnProperty3-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
- The Twelve-Factor App — III. Config — raw/official-docs/config-12-factor-app-config
- Spring Cloud Config (official) — raw/official-docs/config-spring-cloud-config-server-official
- Spring Cloud Kubernetes — ConfigMap auto-reload — raw/official-docs/config-spring-cloud-kubernetes-configmap-reload
- AWS AppConfig — Feature flag & deployment strategy — raw/official-docs/config-aws-appconfig-feature-flag-deployment
- LaunchDarkly — Feature flag best practice — raw/company-tech-blogs/config-launchdarkly-feature-flag-best-practice
- Spring Boot — Custom AutoConfiguration / starter — raw/official-docs/adapter-spring-boot-autoconfig-custom-starter
- Java SPI —
java.util.ServiceLoader— raw/official-docs/adapter-java-spi-serviceloader - Togglz / FF4J — Feature toggle library — raw/company-tech-blogs/adapter-togglz-ff4j-feature-toggle-library
- ArchUnit — Writing Custom Rules / Accessing Annotation — raw/official-docs/archunit-conditional-on-property-3-layer-pattern (Layer 2 정적 검사 가능 범위 평가, needs-confirmation)
- Canonical: raw/project-notes/ca-skeleton-operational-contract (§9, §11, §29 Group G-I)