Files
llm-wiki/raw/interviews/startup-fail-fast-config-validation-2026-06-06.md

51 lines
3.6 KiB
Markdown

---
title: interview / startup-fail-fast-config-validation-2026-06-06
source_type: interview-prep
status: raw
related_branches: [feature-env-driven-runtime-configuration]
related_projects: [ca-skeleton]
tags: [interview, ca-skeleton, spring-boot, configuration, fail-fast, validation, lifecycle]
created: 2026-06-06
status_label: captured
---
# interview: startup-fail-fast-config-validation-2026-06-06
> Layer: `raw/interviews/` — env-driven runtime configuration 구현에서 정직하게 도출 가능한 면접 질문/답변 원석.
## Parent / 부모
- [[raw/branch-notes/feature-env-driven-runtime-configuration]]
## Q1. env 조합 기반 fail-fast 검증을 Spring 라이프사이클의 어디에 두어야 하나? `EnvironmentPostProcessor` / `SmartInitializingSingleton` / `ApplicationReadyEvent` 비교
- **결론**: bean **presence** 검사가 필요하면 `SmartInitializingSingleton` 이 적정.
- 근거:
- `EnvironmentPostProcessor` — bean 정의 **이전**에 실행. property 값은 보지만 bean 존재 여부는 알 수 없음 → multi-instance 5종 bean presence 검사 불가.
- `SmartInitializingSingleton#afterSingletonsInstantiated` — 모든 non-lazy singleton 초기화 **직후**, context refresh 완료 **전** 1회. bean presence 검사 가능 + 위반 시 `throw` 하면 context 가 기동 거부.
- `ApplicationReadyEvent` — 트래픽 수용 **직전**. 너무 늦음(이미 포트 바인딩/warm-up 비용 지불 후 실패).
- 보강: 동일 계약을 contract test 로 이중화해 CI 회귀 방지.
## Q2. `@ConfigurationProperties` 검증을 "선언적 JSR-303" 과 "compact constructor throw" 로 나누는 기준은?
- **단순 제약**(필수·범위·정규식): `@Validated` + JSR-303(`@NotBlank`/`@PositiveOrZero`/`@Min` …) 선언. startup 시 `BindValidationException` 자동 발생.
- **조건부/교차필드**(JSR-303 로 표현 불가): record compact constructor 에서 검사 후 invalid 면 `throw`(fail-fast). 예) `enabled=true` 일 때만 `origins` 필수.
- **정상 default**(absent → 안전한 기본값, 예 `enabled=false` 시 빈 origins)는 invalid 아님 → default 허용.
- 안티패턴: invalid 값을 `log.warn` + 조용히 기본값으로 대체(lenient). 운영 misconfig 가 숨는다.
## Q3. prod 안전 가드에서 Spring profile 매칭을 case-sensitive 로 할까 case-insensitive 로 할까?
- `Environment#matchesProfiles` / `acceptsProfiles`**case-sensitive**. 따라서 `SPRING_PROFILES_ACTIVE=PROD`(대문자 오타)는 `"prod"` 와 매칭되지 않아 prod 가드를 **우회**할 수 있음.
- prod-unsafe 토글(내부 에러 노출 / body 로깅)을 막는 가드라면, 오타로 가드가 풀리는 것이 더 위험 → **의도적으로 `equalsIgnoreCase` 로 대문자 변형까지 잡는 편이 안전**.
- 트레이드오프: case-insensitive 는 profile expression(`!prod`, `prod | staging`)을 지원하지 않음. 표현식이 필요하면 `matchesProfiles` 를, 단순 단일 profile 안전가드면 case-insensitive 동등 비교를 선택.
## Q4. optional capability bean 을 "이름"으로 presence 검사하는 것의 장단점
- 장점: 해당 capability 의 **구체 타입이 아직 존재하지 않아도**(다른 branch 가 미구현) 계약(bean name)만으로 검사 가능 → skeleton 단계에서 cross-branch 계약을 강제.
- 단점: 이름 오타에 취약, 타입 안전성 없음. → 계약 이름을 `static final` 상수 + 주석(owner branch)으로 고정하고 contract test 가 상수를 직접 참조하게 해 drift 를 줄임.
## 관련 / Related
- [[raw/branch-notes/feature-env-driven-runtime-configuration]]
- [[raw/errors/global-sed-env-rename-pitfalls-2026-06-06]]