Files
DongHyeonkaandClaude Fable 5.1 b25357c48a docs(clean-architecture-backend-template): fold analysis into final and re-select one topic
- analysis/·source-index·state.json 을 final/document.md 제2부·제3부로 접었다. SSOT 는 하나다
- 파일럿 — commit-ambiguity-as-a-result 를 새 기준으로 재선별. 후보 14 → 글감 5
  (PROMOTE 5 · MERGE_INTO 3 · KEEP_IN_SSOT 4 · 보류 2). 기록 5건을 다시 썼고 그림 1개를
  techviz 로 만들었다
- 재선별이 잡은 것: 제1부 §6.2·§11.1 이 자기 §13.2 와 어긋나 있었다(레인을 안 돌렸다 vs
  돌렸다) — 정정. 이미 답이 나와 있던 Question 을 HEAD 재실행 질문으로 다시 세웠다.
  Concept 이 인용한 코드가 SSOT 에 없어 뺐다
- candidateScope·sourceRepository 기록. 나머지 43개 주제는 재선별 대기(PENDING 905)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-07 12:39:20 +09:00

5.0 KiB

kind, slug, title, topic, project, status, sourceRevision, rootTreeNode, evidenceCapturedOn, body, assets, evidence, source
kind slug title topic project status sourceRevision rootTreeNode evidenceCapturedOn body assets evidence source
CASE observation-downgraded-by-the-composition 관측을 필수 생성자 인자로 만든 수정을 조립이 6인자 생성자로 되돌렸다 assembly-ownership clean-architecture-backend-template 게시 전 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 case:observation-downgraded-by-the-composition 2026-09-01 case-observation-downgraded-by-the-composition.body.md
key file
observation-downgraded-by-the-composition ../../../final/evidence/rendered/observation-downgraded-by-the-composition.svg
../../../final/evidence/raw/observation-downgraded-by-the-composition.txt
../../../final/evidence/raw/tl-messaging-observation-noop.txt
원본 분석 절은 final/document.md#5-2 · final/document.md#a19 §5.1 이다.

관측을 필수 생성자 인자로 만든 수정을 조립이 6인자 생성자로 되돌렸다

발행기는 관측 구현을 필수 인자로 요구하는 생성자를 갖고 있다. 자동설정이 관측 인자가 없는 짧은 생성자를 부르고, 그 생성자는 no-op 관측으로 위임한다. 출하 배포에서 메시징 관측은 아무것도 기록하지 않는다.

관계

  • @Bean이 있다는 것은 조립 증거가 아니다 타입이 요구하는 것과 조립이 넘기는 것이 다를 수 있다는 사례다.
  • 조립 결함을 판정하려면 조립하는 쪽을 먼저 읽어야 한다 발행기만 읽으면 관측이 필수로 보인다.
  • outbox가 둘이고, 출하되는 것은 messaging 플랫폼 쪽이 아니다 같은 조립 지점에서 나온 다른 공백이다.

문제

DefaultMessagePublisher 는 생성자가 둘이다.

7인자 : 관측 인자가 없고, NO_OBSERVATION 으로 위임한다 8인자 : 관측을 받고 Objects.requireNonNull 로 검사한다

8인자 쪽 javadoc 은 그것이 모든 결과를 기록하는 발행기라고 적는다. 7인자 쪽은 주입 가능한 시계를 위한 것이라고 적는다.

NO_OBSERVATION 은 필드 javadoc 이 그 성격을 밝힌다. 메트릭을 배선하지 않은 배포를 위한 no-op 관측이다. 여섯 개 기록 메서드가 전부 빈 본문이다.

결론

자동설정이 6인자 호출을 한다.

MessagingCoreAutoConfiguration 의 messagingPublisher 빈은 여섯 개 협력자만 받아 6인자 생성자를 호출한다. 그 생성자는 다시 7인자로, 7인자는 8인자로 NO_OBSERVATION 을 넣어 위임한다.

결과적으로 출하 배포의 발행기는 발행도, 전달도, 정산도, 백로그도, 진단도 기록하지 않는다. 관측 인터페이스는 존재하고 구현체도 존재하지만 그 사이를 잇는 조립이 없다.

이 실패의 성격은 조용하다. 빈은 생성되고 발행은 정상 동작하며 로그에도 신호가 없다. no-op 구현이 명시적으로 존재하기 때문에 널 참조도 예외도 나지 않는다. 관측이 꺼진 것과 관측이 배선되지 않은 것이 런타임에서 구별되지 않는다.

@ConditionalOnMissingBean 이 붙어 있으므로 애플리케이션이 자기 MessagePublisher 빈을 등록하면 이 자동설정은 물러난다. 그러나 이 저장소의 출하 컴포지션은 그렇게 하지 않는다.

검증 환경

OpenJDK : 21.0.12 Gradle : 9.0.0 Spring Boot : 4.0.8 확인 방식 : 정적 도달성 확인. 애플리케이션을 부팅하지 않았다 소스 수정 : x

재현 조건

원문은 final/evidence/raw/tl-messaging-observation-noop.txt 에 있다.

  1. DefaultMessagePublisher 의 생성자 두 개와 NO_OBSERVATION 필드를 읽는다.
  2. 6인자 호출이 7인자로, 7인자가 8인자로 위임하며 관측 자리에 NO_OBSERVATION 이 들어가는 경로를 확인한다.
  3. MessagingCoreAutoConfiguration 의 messagingPublisher 빈이 몇 개의 인자로 생성자를 부르는지 확인한다.

본문

관측을 선택적 데코레이터가 아니라 필수 생성자 인자로 만든 수정이 runtime-core에 있고 그 javadoc이 "an unobserved publish path is how 'the dashboards were empty during the incident' happens"로 이유를 적는다.

관측을 필수 인자로 만든 수정

:::evidence key="observation-downgraded-by-the-composition" alt="분석 문서 final/document.md 에서 이 기록의 근거 절을 그대로 잘라낸 18줄. 코드베이스를 측정한 것이 아니라 원본 판정이 무엇을 적었는지를 보여 준다." caption="final/document.md 발췌 — 18줄" zoom="true" :::

조립이 그 수정을 되돌린다

자동설정은 6인자 생성자를 골라 NO_OBSERVATION(다섯 메서드 전부 빈 본문)을 주입하고, 방출자 넷은 main 참조 0이며 등록되는 것은 협력자 둘뿐이다.

같은 경로가 예외 메시지를 의도적으로 버린다

둘이 합쳐지면 진단 흔적이 남지 않는다.

확인하지 못한 것

애플리케이션을 부팅해 액추에이터에서 messaging 메트릭 시리즈의 부재를 관측하지 않았다. 부팅 한 번이면 확증된다.