--- title: error / spring-configuration-bean-factory-method-not-processed-2026-06-11 source_type: error-note status: raw related_branches: [feature-outbound-http-client-baseline] related_projects: [ca-skeleton] tags: [error, ca-skeleton, spring, configuration, testing, applicationcontextrunner] created: 2026-06-11 status_label: resolved --- # error: spring-configuration-bean-factory-method-not-processed-2026-06-11 > Layer: `raw/errors/` — 작업 중 마주친 단일 실패·트러블슈팅 기록. 원본은 raw에 영구 보관한다. ## Parent / 부모 - [[raw/branch-notes/feature-outbound-http-client-baseline]] — D3 활성화 가드(retry enabled + MeterRegistry 부재 → 기동 실패) 테스트 작성 중 발생. ## 증상 / Symptom - 에러 메시지 (원문 그대로): ```text OutboundHttpResilienceConfigTest > application_context_fails_to_start_when_retry_enabled_and_no_meter_registry_bean() FAILED java.lang.AssertionError at OutboundHttpResilienceConfigTest.java:138 ``` - 발생 컨텍스트: `ApplicationContextRunner` 테스트가 `assertThat(ctx).hasFailed()` 를 어서션 — retry enabled + MeterRegistry 부재이므로 `OutboundHttpResilienceConfig.outboundHttpResilience()` 가 `IllegalStateException` 으로 기동을 실패시켜야 하는데, 컨텍스트가 **정상 기동**해 버림. - 발생 환경: local, Spring Boot 3.5.14 테스트 (`ApplicationContextRunner`). - 재현 가능 여부: `always`. ## 재현 절차 / Reproduction 1. 테스트 inner `@Configuration` 클래스에 `@Bean OutboundHttpResilienceConfig resilienceConfig() { return new OutboundHttpResilienceConfig(); }` 처럼 **다른 @Configuration 클래스를 @Bean 팩토리 메서드의 반환값으로 등록**. 2. `ApplicationContextRunner.withUserConfiguration(테스트Config.class).run(...)`. 3. 기대: `OutboundHttpResilienceConfig` 안의 `@Bean outboundHttpResilience(...)` 정의가 처리되어 기동 시 IllegalStateException. 4. 실제: 그 `@Bean` 메서드가 아예 빈 정의로 등록되지 않음 → 가드 코드가 실행되지 않고 컨텍스트 정상 기동 → `hasFailed()` 어서션 실패. ## 조사 단계 / Investigation log - 2026-06-11 — 컨텍스트가 실패하지 않는 이유 추적 → `ConfigurationClassPostProcessor` 는 빈 정의의 클래스가 configuration 후보일 때만 `@Bean` 메서드를 처리하는데, **팩토리 메서드 산출물로 등록된 빈**은 그 대상이 아님(인스턴스가 단순 빈으로만 등록) → `@Configuration` 클래스는 `withUserConfiguration(...)` 등으로 **직접 구성 클래스로 등록**해야 함. - 2026-06-11 — 테스트 수정: `resilienceConfig()` @Bean 메서드 제거 + `.withUserConfiguration(RetryEnabledNoMeterConfig.class, OutboundHttpResilienceConfig.class)` 로 등록, 불필요한 `@EnableAutoConfiguration` 도 제거 → 컨텍스트가 기대대로 기동 실패, `getStartupFailure().getMessage()` 에 "MeterRegistry" 포함 확인, green. ## 근본 원인 / Root cause - 직접 원인: `@Configuration` 클래스를 다른 구성 클래스의 `@Bean` 팩토리 반환값으로 등록하면 그 안의 `@Bean` 메서드들이 빈 정의로 처리되지 않음. - 근본 원인: Spring 의 구성 클래스 처리(`ConfigurationClassPostProcessor`)는 "구성 클래스로 등록된 빈 정의"를 스캔 단위로 삼는다 — 팩토리 메서드 산출 인스턴스는 평범한 빈일 뿐 구성 클래스 향상(enhancement)·@Bean 스캔 대상이 아니다. - 트리거 조건: 테스트에서 구성 클래스를 "new 해서 @Bean 으로 돌려주는" 식으로 우회 등록할 때. ## Sources / 근거 - 로컬 검증: `OutboundHttpResilienceConfigTest` — 수정 전 `hasFailed()` AssertionError / 수정 후 green (`./gradlew :adapter-outbound:test`). Spring 공식 문서의 해당 절 인용은 미보강 (`needs-confirmation` — @Configuration javadoc/reference 의 lite mode 절 추가 인용 권고). ## 해결 / Resolution - 적용한 조치: 테스트의 구성 등록 방식을 `.withUserConfiguration(..., OutboundHttpResilienceConfig.class)` 직접 등록으로 교체, `@Bean` 팩토리 등록 제거. - 검증 방법: `./gradlew :adapter-outbound:test` — 해당 테스트 포함 모듈 전체 green. - 잔여 위험: 없음 (테스트 배선 문제 — 프로덕션 경로는 component-scan 으로 정상 등록). ## 회고 / Lessons - 빨리 감지하는 신호: "컨텍스트가 실패해야 하는데 hasNotFailed/정상 기동" + 문제의 @Bean 정의가 컨텍스트에 아예 없음 → 구성 클래스 등록 경로(직접 등록 vs 팩토리 산출물)부터 확인. - 예방 체크리스트: `ApplicationContextRunner` 에서 @Configuration 클래스는 항상 `withUserConfiguration(...)`/`withConfiguration(...)` 으로 직접 등록한다. @Bean 으로 돌려주지 않는다. - wiki 일반화 후보: "Spring 구성 클래스는 '등록 방식'이 처리 여부를 결정한다 — 팩토리 산출 @Configuration 의 @Bean 은 죽은 정의" (wiki/concepts 추출 후보). ## Related / 관련 - 관련 에러: [[raw/errors/micrometer-meterfilter-replacetagvalues-functioncounter-2026-06-11]], [[raw/errors/jdk-httpclient-dns-unresolvedaddress-connectexception-2026-06-11]] — 같은 branch 작업에서 발생.