Files
llm-wiki/raw/errors/archunit-b7-configprops-nested-record-accessor-outbound-2026-06-13.md

4.6 KiB

title, source_type, status, related_branches, related_projects, tags, created, status_label
title source_type status related_branches related_projects tags created status_label
error / archunit-b7-configprops-nested-record-accessor-outbound-2026-06-13 error-note raw
feature-background-job-async-contract
feature-outbound-http-client-baseline
ca-skeleton
error
ca-skeleton
archunit
configuration-properties
record
adapter-outbound
pre-existing
2026-06-13 unresolved

error: archunit-b7-configprops-nested-record-accessor-outbound-2026-06-13

Layer: raw/errors/ — 작업 중 마주친 단일 실패·트러블슈팅 기록. 원본은 raw에 영구 보관한다.

Parent / 부모

증상 / Symptom

  • 에러 메시지 (원문 그대로):
    CleanArchitectureTest > outbound_adapter_method_returns_only_domain_or_primitives FAILED
      Architecture Violation [Priority: MEDIUM] - Rule 'B7: outbound adapter public methods
      must return domain types (or primitives/wrappers/Optional) ...' was violated (2 times):
      Method <...OutboundHttpSettings.circuitBreaker()> has raw return type ... in (OutboundHttpSettings.java:36)
      Method <...OutboundHttpSettings.retry()> has raw return type ... in (OutboundHttpSettings.java:36)
    
  • 발생 컨텍스트: :app-bootstrap:test 전체 실행 시 257개 중 1개 실패. async/background-job 변경분(256개)은 전부 green.
  • 발생 환경: local, Gradle, Spring Boot 3.5.x.
  • 재현 가능 여부: always.

재현 절차 / Reproduction

  1. 현재 HEAD(feature/domain-event-outbox-contract, commit f5e2311)에서 background-job 변경분을 git stash -u 로 전부 치워 working tree 를 깨끗이 한다.
  2. cd src && ./gradlew :app-bootstrap:test --tests '*CleanArchitectureTest' 실행.
  3. 결과: 50 tests, 1 failed — outbound_adapter_method_returns_only_domain_or_primitives 가 동일하게 실패.
  4. 결론: 이 실패는 background-job 변경과 무관한 선재(pre-existing) 실패. (background-job 변경분을 다시 pop 해도 실패 1건은 동일.)

근본 원인 / Root cause

  • 직접 원인: OutboundHttpSettings(@ConfigurationProperties record, ..adapter.outbound.httpclient 패키지)의 accessor 메서드 retry() / circuitBreaker() 가 같은 패키지의 중첩 record OutboundHttpSettings.Retry / OutboundHttpSettings.CircuitBreaker 를 반환한다. B7 ArchUnit 규칙은 outbound adapter 의 public 메서드 반환형을 domain/primitive/wrapper/Optional 로 제한하고 @Configuration @Bean 팩토리 메서드만 예외 처리한다 — @ConfigurationProperties record 의 component accessor 는 예외 목록에 없다.
  • 근본 원인: feature-outbound-http-resilience-config 작업(중첩 Retry/CircuitBreaker record 도입, commit d702572/2613561)이 B7 규칙의 예외 목록을 함께 갱신하지 않음. 규칙이 새 코드 형태(설정 record 의 중첩 record accessor)를 모름.
  • 트리거 조건: outbound 패키지의 @ConfigurationProperties record 가 중첩 설정 record 를 accessor 로 노출.

Sources / 근거

  • 로컬 검증: git stash -u baseline 에서 :app-bootstrap:test --tests '*CleanArchitectureTest' → 동일 1건 실패 확인(50 tests, 1 failed). background-job 변경분 적용 후에도 동일 1건만 실패(257 tests, 1 failed) — 신규 위반 0건.
  • 옵션 A: B7 규칙에 @ConfigurationProperties 타입의 component accessor 를 예외로 추가(@Configuration @Bean 예외와 동일 취지 — 설정 record 는 adapter 응답 표면이 아니다).
  • 옵션 B: 중첩 Retry/CircuitBreaker record 를 settings 전용 별도 위치/패키지로 분리해 B7 스코프(..adapter.outbound.. 응답 표면)에서 제외.
  • 본 background-job branch 범위 밖이라 수정하지 않음. owner = feature-outbound-http-client-baseline / feature-outbound-http-resilience-config 에 이관 권고. 그 전까지 ./gradlew check 는 이 1건으로 red.

교훈 / Lesson

  • 새 코드 형태(중첩 설정 record, 새 어노테이션 패턴)를 도입할 때는 그것을 검사하는 ArchUnit 규칙의 예외 목록을 같은 PR 에서 갱신해야 한다 — "guardrail 이 새 코드를 모르면 지키지 못한다"(root CLAUDE.md).
  • 새 기능을 올리기 전 ./gradlew check 가 이미 red 인지 baseline 확인(git stash 후 실행)을 습관화하면, 내 변경과 선재 실패를 정직하게 분리할 수 있다.