init: 클린 아키텍처 백엔드

This commit is contained in:
DongHyeonka
2026-07-24 14:29:36 +09:00
parent 9eed16d097
commit 821fe00c32
971 changed files with 74769 additions and 1 deletions
+44
View File
@@ -0,0 +1,44 @@
# adapter:outbound:messaging — 설계 결정 참조
메시징(broker publish + outbox) 아웃바운드 어댑터 모듈. 패키지 루트:
`dev.caskeleton.adapter.outbound.messaging`. `:adapter:outbound:support` 에 의존해 공유
correlation / fail-open 의존성 로깅을 재사용한다.
허용/금지 의존 정책은 `src/build.gradle`
`allowedProjectDependencies['adapter:outbound:messaging']` 항목이 SSOT 다(이 모듈은 아직 별도
CLAUDE.md 를 두지 않았다). 이 문서는 코드 주석에서 덜어낸 **설계 결정의 근거**를 모아둔 참조용
기록이다.
## 모듈 개요
application-core 포트(`MessagePublisher` / `OutboxMessagePublishPort`) 뒤에 두는 **선택형**
연동 어댑터다. `@ConditionalOnProperty` 로 게이팅되고 기본 비활성이며, 비활성 바인딩은
`Disabled*` 구현으로 fail-fast 한다(Layer 3). 무거운 broker SDK 는 의도적으로 classpath 에
최소화하고, 실제 broker client(`KafkaSender`)는 포킹 프로젝트가 채우는 seam 이다.
## 두 포트를 하나의 활성 broker 에 조립
`MessagingConfig` 는 두 messaging 포트를 단일 활성 `MessageBroker` 위에 조립한다 — broker
추가는 새 broker 구현 파일 추가만으로 끝나고 이 config 는 바뀌지 않는다.
## broker 선택 검증
`app.messaging.broker` 가 설정됐는데 `MessageBroker` 빈이 없으면 startup 을 명시적 메시지로
실패시킨다(조용한 no-op 아님). settings 와 활성 빈의 `brokerId()` 불일치도 startup 실패다.
## 비활성 sentinel 두 개를 분리한 이유
`DisabledMessagePublisher``DisabledOutboxMessagePublisher` 는 별도 클래스다 — 한 클래스가
두 포트를 모두 구현하면 `getBean(MessagePublisher.class)` 가 모호해진다.
## OutboxEnvelopeJson — 손수 짠 JSON
이 모듈은 `jackson-databind` 를 classpath 에 두지 않아(스켈레톤을 가볍게 유지) outbox envelope
직렬화는 의존성 없는 손수 짠 JSON 이다.
## MessagePublisher vs OutboxMessagePublishPort
`MessagePublisher` 는 fail-open 어댑터-로컬 발행기로, 발행 실패를 correlationId 와 함께
로깅하고 삼켜(→ `:adapter:outbound:support``FailOpenDependencyLogger`) outbox/retry 로
위임하므로 core 5xx 가 되지 않는다. 내구성 있는 전달이 필요하면 `OutboxMessagePublishPort`
쓴다. 반환 타입을 void 로 둬 broker SDK 타입이 어댑터 밖으로 새지 않는다(B7).