--- kind: CASE slug: conditionalonbean-evaluated-at-parse-time title: '@ConditionalOnBean(DataSource.class)가 클래스 파싱 시점에 평가되어 여덟 빈이 사라졌다' topic: assembly-ownership project: clean-architecture-backend-template status: 게시 전 sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 rootTreeNode: case:conditionalonbean-evaluated-at-parse-time evidenceCapturedOn: 2026-09-01 assets: - key: conditionalonbean-evaluated-at-parse-time file: ../../../final/evidence/rendered/conditionalonbean-evaluated-at-parse-time.svg evidence: - ../../../final/evidence/raw/conditionalonbean-evaluated-at-parse-time.txt source: - 원본 분석 절은 final/document.md#a05 §14.4 이다. --- # @ConditionalOnBean(DataSource.class)가 클래스 파싱 시점에 평가되어 여덟 빈이 사라졌다 @Import 로 들어오는 설정 클래스에 붙은 @ConditionalOnBean 이 데이터소스 빈 정의가 생기기 전에 평가되어 항상 거짓이었다. 여덟 빈이 조용히 사라졌고, 아무것도 그것을 보고하지 않았다. ## 관계 - **조건부 빈의 평가 시점 — 파싱 시점과 등록 시점** 이 사례가 설명하는 메커니즘이다. - **ConditionalOnBean 사슬의 실제 평가 순서를 확인하지 않았다** 이 함정이 현재 리비전에도 남아 있는지에 대한 미해결 질문이다. - **이름만 AutoConfiguration이던 세 클래스가 capability 리포트에 Stable로 올라 있었다** 같은 클래스에서 앞서 일어난 결함이다. ## 문제 이 클래스는 예전에 @ConditionalOnBean(DataSource.class) 를 갖고 있었다. 문제는 이 클래스가 자동설정으로 등록되는 것이 아니라 PersistenceJpaRootAutoConfiguration 이 @Import 로 끌어온다는 점이다. 그래서 조건이 클래스 파싱 시점에 평가된다. 데이터소스 빈 정의가 아직 존재하지 않는 시점이다. 따라서 조건은 실제 배포 전부에서 거짓이었다. ## 결론 여덟 빈이 조용히 사라졌다. 아무것도 그것을 보고하지 않았다. 그 여덟에 의존하는 것이 없었기 때문이다. 결함이 드러난 것은 데이터소스 검증기가 마침내 호출자에 연결되고 JPA Compose 레인이 적격 빈 없음이라고 답했을 때다. 수정은 조건의 순서를 바꾸는 것이 아니라 조건을 제거하는 것이었다. 근거는 이렇다. 이 클래스는 JPA 루트를 통해서만 도달하고 그 루트가 이미 마스터 스위치를 갖고 있으므로, 파싱 시점에는 데이터소스가 있느냐는 질문에 이미 예라고 답한 상태다. 데이터소스가 필요한 빈은 그것을 파라미터로 받고, 스위치가 켜진 채 데이터소스가 없으면 시끄러운 실패가 된다. 계층이 사라지는 것보다 그쪽이 원하던 결과다. ## 검증 환경 OpenJDK : 21.0.12 Gradle : 9.0.0 Spring Boot : 4.0.8 근거 : 저장소의 javadoc 이 사후 기록으로 남긴 회귀 소스 수정 : x ## 재현 조건 수정된 형태를 확인하는 절차다. 1. JpaPlatformRuntimeAutoConfiguration 의 클래스 javadoc 다섯 번째와 여섯 번째 문단을 읽는다. 2. 현재 클래스 애너테이션에 ConditionalOnBean 이 없고 ConditionalOnClass 와 ConditionalOnProperty 만 있는지 확인한다. 3. PersistenceJpaRootAutoConfiguration 이 이 클래스를 Import 하는지 확인한다. ## 본문 이 클래스는 루트가 **import**하지 auto-configure하지 않으므로, 그 조건이 클래스 파싱 중 — datasource 빈 정의가 존재하기 전에 — 평가됐고 따라서 **모든 실제 배포에서 false**였다. ## 조건이 평가된 시점 :::evidence key="conditionalonbean-evaluated-at-parse-time" alt="분석 문서 final/document.md#a05 에서 이 기록의 근거 절을 그대로 잘라낸 16줄. 코드베이스를 측정한 것이 아니라 원본 판정이 무엇을 적었는지를 보여 준다." caption="final/document.md#a05 발췌 — 16줄" zoom="true" ::: ## 여덟 빈이 조용히 사라졌다 아무것도 그중 어느 것에도 의존하지 않아 아무것도 보고하지 않았다. ## 드러난 시점 datasource validator가 caller에 배선되고 Compose 레인이 "No qualifying bean"이라고 답했을 때다. 같은 함정을 피하려고 루트의 검사가 validator를 주입받지 않고 직접 생성한다. ## 확인하지 못한 것 현재 리비전의 다른 조건부 빈들이 각각 어느 시점에 평가되는지 런타임에서 확인하지 않았다. debug 부팅의 조건 평가 리포트가 그것을 답한다. 현재 리비전에서 재발하지 않는지 ConditionEvaluationReport로 확인하지 않았다