refactor: 문서 개선 중

This commit is contained in:
donghyeon-ka
2026-09-21 14:30:55 +09:00
parent c93cdea150
commit 805a18f486
1497 changed files with 525837 additions and 59152 deletions
@@ -29,7 +29,7 @@ source:
- **같은 개념의 두 어휘가 공존하면 하나를 죽은 것으로 표시한다**
`rabbit` 은 등록 목록에 남고 `assemblableBrokerIds()` 에서는 빠진다. 그 필드 자바독이 이 이름이 언제 맵을 떠나는지까지 적는다.
- **문서 계약 테스트의 단언 경계 밖에 발견된 드리프트 세 건이 전부 있었다**
그 기록이 경계 밖으로 지목한 셋 중 하나가 브로커 등급 표의 제한 칸이고, 이 사례가 그 칸에서 빠진 사실이다.
그 기록은 브로커 등급 표의 제한 칸도 경계 밖으로 지목했고, 이 Case에서는 실제 선택 불가 조건이 그 칸에 기록되지 않았다.
## 문제
@@ -45,7 +45,7 @@ source:
그 구현이 시험에는 둘 있는데 성격이 다르다. RabbitRuntimeTest:48 이 만드는 것은 아무 데도 붙지 않는 더블이다. RabbitBrokerIT:93 은 nextPublishSequence 를 channel.getNextPublishSeqNo 로 잇고 publish 를 :187 의 channel.basicPublish 까지 위임하며, :61 의 Testcontainer 에 붙어 :154·:161 이 브로커의 큐 깊이를 읽는다.
채택자가 그 seam 을 채워도 소용이 없다. messaging-rabbit/build.gradle:12~:14 는 seam 을 구현할 소비자를 위해 spring-amqp 를 api 로 노출한다고 적는다. 그런데 :147 의 selectImports 가 selectedBroker 를 먼저 부르므로 :123 의 예외가 자동설정 import 이전에 터진다. KafkaMessagingAutoConfiguration:163 @ConditionalOnMissingBean 으로 자기 전송 빈에 탈출구를 두었는데 rabbit 에는 그 자리가 없다.
채택자가 그 seam 을 채워도 소용이 없다. messaging-rabbit/build.gradle:12~:14 는 seam 을 구현할 소비자를 위해 spring-amqp 를 api 로 노출한다고 적는다. 그런데 :147 의 selectImports 가 selectedBroker 를 먼저 부르므로 :123 의 예외가 자동설정 import 이전에 터진다. KafkaMessagingAutoConfiguration:163은 `@ConditionalOnMissingBean`으로 자기 전송 빈을 대체할 수 있게 했지만 Rabbit 자동설정에는 같은 대체 조건이 없다.
RabbitMessagingAutoConfiguration 이 선언하는 빈은 :35·:48·:70·:94 넷이고 그중 전송이 없다. 선택이 먼저 던지므로 이 넷도 만들어지지 않는다.
@@ -57,21 +57,21 @@ RabbitMessagingAutoConfiguration 이 선언하는 빈은 :35·:48·:70·:94 넷
같은 문서 :23~:27 은 messaging 리프가 모두 runtime_memberships 가 비어 build-only 라는 단서를 표 전체에 붙인다. 그 단서도 지금은 맞지 않는다. configuration-reference.md:132 은 이 브로커의 설정 예시를 싣고, docs/registries/env-keys.yaml 은 이 프로퍼티에 허용값 목록도 검증 규칙도 걸지 않는다.
문서 계약 시험은 이 차이를 볼 수 없다. 여덟 중 두 개만 브로커 등급 표에 닿고, 그 둘이 확인하는 것은 어댑터 이름과 등급 낱말의 조합뿐이다.
문서 계약 시험 여덟 중 브로커 등급 표를 보는 것은 둘뿐이며, 두 테스트는 어댑터 이름과 등급 낱말의 조합만 확인한다.
거절 로직 자체도 시험이 없다. 이름을 가진 시험 파일이 0 개이고, env-keys.yaml:3326 이 요구하는 adapter-contract:messaging-broker-selection 을 정의한 자리도 0 개다.
거절 로직 자체도 시험이 없다. 이름을 가진 시험 파일이 0 개이고, `env-keys.yaml:3326`이 요구하는 `adapter-contract:messaging-broker-selection`의 정의도 저장소에서 찾지 못했다.
## 검증 환경
OpenJDK : 21.0.12
확인 방식 : 선택기의 거절 맵과 자바독과 예외 인용, 그 선택을 붙드는 시험 파일과 호출자 계수 및 레지스트리가 요구하는 시험 id 의 정의 여부, 채널 발행자가 나오는 자리 전수와 구현 형태별 계수, 두 익명 구현의 본문과 컨테이너 배선 인용, build.gradle 의 seam 공개 주석과 Kafka 쪽 조건 애너테이션과 selectImports 순서 대조, 두 자동설정의 빈 목록, 출하 파일 수와 물리적 줄과 빈 줄 제외 줄, 전송 클래스의 자기 호칭과 호환성 표의 등급, 지원 매트릭스 표와 그 전체에 붙은 단서와 startup 언급 전수, 문서 계약 시험의 단언 범위, 이 상태를 적는 문서와 운영 설정 문서 대조
확인 방식 : 선택기의 거절 맵과 자바독과 예외 인용, 그 선택을 붙드는 시험 파일과 호출자 계수 및 레지스트리가 요구하는 시험 id 의 정의 여부, 채널 발행자 이름의 모든 사용 지점과 구현 형태별 계수, 두 익명 구현의 본문과 컨테이너 배선 인용, build.gradle 의 seam 공개 주석과 Kafka 쪽 조건 애너테이션과 selectImports 순서 대조, 두 자동설정의 빈 목록, 출하 파일 수와 물리적 줄과 빈 줄 제외 줄, 전송 클래스의 자기 호칭과 호환성 표의 등급, 지원 매트릭스 표와 그 전체에 붙은 단서와 startup 언급 전수, 문서 계약 시험의 단언 범위, 이 상태를 적는 문서와 운영 설정 문서 대조
소스 수정 : x
## 재현 조건
1. 선택기의 거절 맵과 자바독, 그리고 예외를 던지는 자리를 인용한다.
1. 선택기의 거절 맵과 javadoc, 그리고 예외를 생성하는 코드를 인용한다.
2. 그 선택을 검증하는 시험 파일과 selectedBroker 호출자를 세고, 레지스트리가 요구하는 시험 id 가 정의돼 있는지 본다.
3. 채널 발행자 이름이 나오는 자리를 전부 찾아 implements 와 익명 구현을 나눠 세고, 대조 타입 MessagingTransport 같은 검색을 걸어 0 이 아닌 수가 나오는지 확인한다.
3. 채널 발행자 이름의 사용 지점을 전부 찾아 `implements`와 익명 구현을 나눠 세고, 대조 타입 `MessagingTransport`에도 같은 검색을 적용한다.
4. 두 익명 구현의 본문과 그 파일의 컨테이너 배선을 인용한다.
5. build.gradle 의 의존 노출 주석, Kafka 전송 빈의 조건 애너테이션, selectImports 의 호출 순서를 나란히 놓는다.
6. 두 브로커의 자동설정이 만드는 빈을 대조한다.
@@ -86,20 +86,20 @@ OpenJDK : 21.0.12
`MessagingProviderSelection``app.messaging.broker` 값 하나로 전송을 고른다. 등록되지 않은 이름, 클래스패스에 없는 클라이언트, 전송이 아직 없는 브로커를 각각 다른 메시지로 거절한다.
## 선택기가 rabbit 을 거절하는 자리
## 선택기가 rabbit을 거절하는 흐름
:::evidence key="an-unselectable-broker-listed-with-features" alt="저장소 루트에서 돌린 정적 검색과 선택기 프로브의 출력 296줄. 먼저 MessagingProviderSelection 48~70번 줄이 실려 BROKERS_WITHOUT_A_TRANSPORT 맵과 그 필드 자바독이 보이는데, rabbit 어댑터가 검증기와 보안 설정은 출하하지만 전송이 없고 네이티브 채널 다리에 시험 구현만 있다는 것, 그리고 항목이 이 맵을 떠나는 날은 전송이 실제로 생기는 날이라는 것을 적는다. 118~132번 줄이 선택 시 던지는 예외를 만드는 코드다. 이어서 그 선택기를 직접 부른 프로브 결과가 나온다. 등록된 이름은 kafka 와 rabbit 이고 조립 가능한 이름은 kafka 뿐이며, broker=kafka 는 kafka 로 선택되고, broker=rabbit 은 IllegalStateException 과 함께 전송이 구현되지 않아 발행이 타고 갈 것이 없다는 메시지를 내며, broker=pulsar 는 등록되지 않은 전송이라는 다른 메시지를, 빈 값은 브로커를 지정하라는 또 다른 메시지를 낸다. 다음으로 그 거절을 붙드는 시험이 없다는 것이 나온다. MessagingProviderSelection 을 참조하는 파일은 넷인데 전부 main 이고, env-keys.yaml 3326번 줄이 required_test 로 adapter-contract:messaging-broker-selection 을 선언하는데 그 id 정의한 자리는 0 개다. RabbitChannelPublisher 18~41번 줄이 실려 추상 메서드가 nextPublishSequence 와 publish 둘이라는 것이 보인다. 그 이름이 나오는 자리는 여섯이고 implements 를 가진 파일은 0 개 익명 구현을 가진 파일은 2 개이며, 대조로 실은 implements MessagingTransport 목록은 여섯인데 넷이 main 어댑터이고 둘은 시험 클래스다. 그 두 익명 구현이 나란히 실린다. RabbitBrokerIT 89~108번 줄은 RabbitMessagingTransport 를 만들면서 nextPublishSequence 를 channel.getNextPublishSeqNo 로 잇고 publish 를 그 시험 클래스의 publish 로 위임한다. RabbitRuntimeTest 44~63번 줄은 시퀀스를 AtomicLong 으로 세고 메시지를 리스트에 담는 인메모리 더블이다. 그 IT 가 붙는 브로커로 rabbitmq:4.3-management 컨테이너 선언과 basicPublish 호출과 messageCount 단언 줄이 나온다. 그 아래에 build.gradle 12~14번 줄의 seam 공개 주석, KafkaMessagingAutoConfiguration 163번 줄의 ConditionalOnMissingBean, MessagingProviderSelection 146~147번 줄의 selectImports 가 차례로 실린다. 두 자동설정이 선언하는 빈은 Kafka 일곱과 Rabbit 넷이다. 출하 여부로는 modules.json 417~431번 줄이 messaging-rabbit 의 runtime_memberships 를 app-bootstrap 으로 적고 app-bootstrap/gradle.lockfile 77번 줄이 amqp-client 를 productionRuntimeClasspath 에 싣는다. main 자바 20 개 파일 물리적 줄 2443 빈 줄 제외 2232 이고, RabbitMessagingTransport 27번 줄은 자기를 Stable RabbitMQ adapter 라 부르는데 CompatibilityMatrix 92번 줄은 같은 항목을 EXPERIMENTAL 로 적는다. 운영 문서로는 support-matrix.md 29~38번 줄의 등급 표와 22~27번 줄의 단서, configuration-reference.md 132~146번 줄의 RabbitMQ 설정 절, env-keys.yaml 의 allowed_values null 과 validation none 이 나온다. 문서 계약 시험은 여덟이고 그중 61번과 70번이 등급 이름을 단언하며 제한이나 선택 가능 여부를 담은 줄은 0 개다. 마지막으로 src/messaging/CLAUDE.md 56~63번 줄이 실려 대부분의 leaf 가 app-bootstrap 멤버십을 갖고 배포된 아티팩트가 싣고 있다는 것과 Rabbit 이 shipped, inactive, unqualified 라는 것을 적고, 코드 리뷰 문서도 같은 상태를 적는다." caption="선택기의 거절 맵과 그것을 직접 부른 프로브 네 경우 · 그 거절을 붙드는 시험 0 과 정의되지 않은 required_test · 추상 메서드 둘과 여섯 자리와 두 익명 구현의 본문 · seam 공개와 Kafka 의 탈출구와 selectImports 순서 · modules.json 의 runtime_memberships 와 락파일의 productionRuntimeClasspath · 자기 호칭과 호환성 등급 · 운영 문서 세 곳과 문서 계약 시험 여덟 · 이 상태를 적는 개발 문서 — 296줄 · exit 0" zoom="true"
:::evidence key="an-unselectable-broker-listed-with-features" alt="저장소 루트에서 돌린 정적 검색과 선택기 프로브의 출력 296줄. 먼저 MessagingProviderSelection 48~70번 줄이 실려 BROKERS_WITHOUT_A_TRANSPORT 맵과 그 필드 자바독이 보이는데, rabbit 어댑터가 검증기와 보안 설정은 출하하지만 전송이 없고 네이티브 채널 다리에 시험 구현만 있다는 것, 그리고 항목이 이 맵을 떠나는 날은 전송이 실제로 생기는 날이라는 것을 적는다. 118~132번 줄이 선택 시 던지는 예외를 만드는 코드다. 이어서 그 선택기를 직접 부른 프로브 결과가 나온다. 등록된 이름은 kafka 와 rabbit 이고 조립 가능한 이름은 kafka 뿐이며, broker=kafka 는 kafka 로 선택되고, broker=rabbit 은 IllegalStateException 과 함께 전송이 구현되지 않아 발행이 타고 갈 것이 없다는 메시지를 내며, broker=pulsar 는 등록되지 않은 전송이라는 다른 메시지를, 빈 값은 브로커를 지정하라는 또 다른 메시지를 낸다. 다음으로 그 거절을 붙드는 시험이 없다는 것이 나온다. MessagingProviderSelection 을 참조하는 파일은 넷인데 전부 main 이고, env-keys.yaml 3326번 줄이 required_test 로 adapter-contract:messaging-broker-selection 을 선언하는데 그 id 정의를 찾지 못한다. RabbitChannelPublisher 18~41번 줄이 실려 추상 메서드가 nextPublishSequence 와 publish 둘이라는 것이 보인다. 그 이름의 사용 지점은 여섯이고 implements 를 가진 파일은 0 개 익명 구현을 가진 파일은 2 개이며, 대조로 실은 implements MessagingTransport 목록은 여섯인데 넷이 main 어댑터이고 둘은 시험 클래스다. 그 두 익명 구현이 나란히 실린다. RabbitBrokerIT 89~108번 줄은 RabbitMessagingTransport 를 만들면서 nextPublishSequence 를 channel.getNextPublishSeqNo 로 잇고 publish 를 그 시험 클래스의 publish 로 위임한다. RabbitRuntimeTest 44~63번 줄은 시퀀스를 AtomicLong 으로 세고 메시지를 리스트에 담는 인메모리 더블이다. 그 IT 가 붙는 브로커로 rabbitmq:4.3-management 컨테이너 선언과 basicPublish 호출과 messageCount 단언 줄이 나온다. 그 아래에 build.gradle 12~14번 줄의 seam 공개 주석, KafkaMessagingAutoConfiguration 163번 줄의 ConditionalOnMissingBean, MessagingProviderSelection 146~147번 줄의 selectImports 가 차례로 실린다. 두 자동설정이 선언하는 빈은 Kafka 일곱과 Rabbit 넷이다. 출하 여부로는 modules.json 417~431번 줄이 messaging-rabbit 의 runtime_memberships 를 app-bootstrap 으로 적고 app-bootstrap/gradle.lockfile 77번 줄이 amqp-client 를 productionRuntimeClasspath 에 싣는다. main 자바 20 개 파일 물리적 줄 2443 빈 줄 제외 2232 이고, RabbitMessagingTransport 27번 줄은 자기를 Stable RabbitMQ adapter 라 부르는데 CompatibilityMatrix 92번 줄은 같은 항목을 EXPERIMENTAL 로 적는다. 운영 문서로는 support-matrix.md 29~38번 줄의 등급 표와 22~27번 줄의 단서, configuration-reference.md 132~146번 줄의 RabbitMQ 설정 절, env-keys.yaml 의 allowed_values null 과 validation none 이 나온다. 문서 계약 시험은 여덟이고 그중 61번과 70번이 등급 이름을 단언하며 제한이나 선택 가능 여부를 담은 줄은 0 개다. 마지막으로 src/messaging/CLAUDE.md 56~63번 줄이 실려 대부분의 leaf 가 app-bootstrap 멤버십을 갖고 배포된 아티팩트가 싣고 있다는 것과 Rabbit 이 shipped, inactive, unqualified 라는 것을 적고, 코드 리뷰 문서도 같은 상태를 적는다." caption="선택기의 거절 맵과 그것을 직접 부른 프로브 네 경우 · 그 거절을 붙드는 시험 0 과 정의되지 않은 required_test · 추상 메서드 둘과 여섯 사용 지점과 두 익명 구현의 본문 · seam 공개와 Kafka 의 탈출구와 selectImports 순서 · modules.json 의 runtime_memberships 와 락파일의 productionRuntimeClasspath · 자기 호칭과 호환성 등급 · 운영 문서 세 곳과 문서 계약 시험 여덟 · 이 상태를 적는 개발 문서 — 296줄 · exit 0" zoom="true"
:::
`:63``BROKERS_WITHOUT_A_TRANSPORT``rabbit` 하나를 담고 값은 이유 문자열이다. `:121` 이 그 값을 꺼내고 `:123` 이 프로퍼티 이름과 이유와 오늘 조립 가능한 브로커 목록을 붙여 `IllegalStateException` 을 만든다.
자바독은 이 설계의 이유를 적는다. 거절하지 않으면 코어 설정 깊은 곳에서 `MessagingTransport` 의존이 충족되지 않아, 운영자에게는 자기가 고른 전송이 미완성이라는 사실 대신 빈이 없다는 말이 도달한다는 것이다.
javadoc은 거절하지 않으면 코어 설정 깊은 곳에서 `MessagingTransport` 의존이 충족되지 않아, 운영자가 ‘선택한 전송이 미완성이라는 설명 대신 빈이 없다는 오류를 받게 된다고 적는다.
## 그 거절을 붙드는 시험이 없다
`MessagingProviderSelection` 이나 브로커 선택을 이름에 가진 시험 파일은 0 개다. `selectedBroker` 를 부르는 자리는 `:93` 의 선언과 `:147` 의 호출 둘뿐이고 둘 다 main 이다.
`MessagingProviderSelection` 이나 브로커 선택을 이름에 가진 시험 파일은 0 개다. `selectedBroker`의 사용 지점은 `:93`의 선언과 `:147`의 호출 둘뿐이고 둘 다 main이다.
`docs/registries/env-keys.yaml:3326` 은 이 프로퍼티의 `required_test``adapter-contract:messaging-broker-selection` 을 선언한다. 그 id 정의한 자리는 저장소에 0 개다.
`docs/registries/env-keys.yaml:3326` 은 이 프로퍼티의 `required_test``adapter-contract:messaging-broker-selection` 을 선언한다. 그 id 정의는 저장소에서 찾지 못했다.
맵을 비우거나 키를 고쳐도 실패하는 시험이 없다.
@@ -123,7 +123,7 @@ OpenJDK : 21.0.12
`KafkaMessagingAutoConfiguration:163` 은 전송 빈에 `@ConditionalOnMissingBean(MessagingTransport.class)` 를 걸어 두었다. 애플리케이션이 자기 전송을 주면 양보한다.
rabbit 에는 그 자리가 없다. `:146`\~`:147` `selectImports` `PROVIDER_CONFIGURATIONS.get(selectedBroker(environment))` 를 부르므로, 자동설정이 import 되기 전에 `:123` 의 예외가 터진다. `RabbitChannelPublisher` 를 직접 구현하고 `MessagingTransport` 빈까지 준 배포도 `broker=rabbit` 을 고를 수 없다.
Rabbit 자동설정에는 같은 대체 조건이 없다. `:146`\~`:147``selectImports``PROVIDER_CONFIGURATIONS.get(selectedBroker(environment))` 먼저 부르므로 자동설정이 import되기 전에 `:123`의 예외가 발생한다. `RabbitChannelPublisher` 를 직접 구현하고 `MessagingTransport` 빈까지 준 배포도 `broker=rabbit` 을 고를 수 없다.
## RabbitMessagingAutoConfiguration 에는 전송 빈이 없고 그 넷도 만들어지지 않는다
@@ -151,7 +151,7 @@ rabbit 에는 그 자리가 없다. `:146`\~`:147` 의 `selectImports` 가 `PROV
그 파일에서 제한 칸이나 선택 가능 여부를 담은 줄은 0 개다.
## 원문과 갈리는 자리
## 원문이 다루지 않은 범위
원문은 `RabbitChannelPublisher` 의 구현이 main·test 통틀어 0 건이라고 적었다. `implements` 로 센 것은 0 이 맞지만 시험 두 파일에 익명 구현이 있고, 그중 하나는 실 컨테이너에 붙는다. `BROKERS_WITHOUT_A_TRANSPORT` 의 자바독 자신이 시험 구현만 있다고 적어 이 상태를 정확히 서술한다.
@@ -40,7 +40,7 @@ source:
수치가 문서에 하드코딩되어 있고 그것을 붙드는 게이트가 없다.
빌드 설정에는 리프 수를 검사하는 코드가 없다. 레지스트리 항목이 늘어도 문서의 숫자는 그대로 남는다.
빌드 설정에는 리프 수를 검사하거나 문서 숫자를 갱신하는 코드가 없다. 그래서 레지스트리 항목이 늘어도 문서에 적힌 기존 숫자는 자동으로 바뀌지 않는다.
이 드리프트의 성질은 앞의 사례들과 다르다. 능력 표의 불일치는 동작에 대한 오해를 만들지만, 이 숫자는 동작을 바꾸지 않는다. 대신 문서 전체의 신뢰도를 깎는다. 19 라는 수를 근거로 삼은 서술 — 예를 들어 모듈 경계 설명이나 의존 그래프 서술 — 이 어느 시점의 것인지 알 수 없게 된다.