Files
document-haness/docs/clean-architecture-backend-template/tech-log-studio/assembly-ownership/case/case-observation-downgraded-by-the-composition.md
T
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

98 lines
5.0 KiB
Markdown

---
kind: CASE
slug: observation-downgraded-by-the-composition
title: 관측을 필수 생성자 인자로 만든 수정을 조립이 6인자 생성자로 되돌렸다
topic: assembly-ownership
project: clean-architecture-backend-template
status: 게시 전
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
rootTreeNode: case:observation-downgraded-by-the-composition
evidenceCapturedOn: 2026-09-01
body: case-observation-downgraded-by-the-composition.body.md
assets:
- key: observation-downgraded-by-the-composition
file: ../../../final/evidence/rendered/observation-downgraded-by-the-composition.svg
evidence:
- ../../../final/evidence/raw/observation-downgraded-by-the-composition.txt
- ../../../final/evidence/raw/tl-messaging-observation-noop.txt
source:
- 원본 분석 절은 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 빈이 몇 개의 인자로 생성자를 부르는지 확인한다.
## 본문
<!-- body:start -->
관측을 선택적 데코레이터가 아니라 필수 생성자 인자로 만든 수정이 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 메트릭 시리즈의 부재를 관측하지 않았다. 부팅 한 번이면 확증된다.
<!-- body:end -->