--- 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]]