--- kind: CONCEPT slug: adapter-outbound-notification-c06 title: 상속을 강제하는 장치가 없어 8종 중 3종만 계약을 탄다 topic: identity-and-value-contracts project: clean-architecture-backend-template status: 게시 전 sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 rootTreeNode: concept:adapter-outbound-notification-c06 evidenceCapturedOn: 2026-09-01 assets: - key: adapter-outbound-notification-c06 file: ../../../final/evidence/rendered/adapter-outbound-notification-c06.svg evidence: - ../../../final/evidence/raw/adapter-outbound-notification-c06.txt source: - 원본 분석 절은 final/document.md#a13#L913 이다. module: adapter-outbound-notification --- # 상속을 강제하는 장치가 없어 8종 중 3종만 계약을 탄다 공유 계약 `ProviderAdapterContract`를 실제로 상속하는 어댑터는 8종 중 3종이다. 클래스 javadoc은 새 프로바이더가 같은 질문에 답하지 않고는 추가될 수 없다고 쓰지만, 상속을 강제하는 장치는 없다. ## 본문 공유 계약을 실제로 상속하는 어댑터는 이 셋이다. ```text .../ses/SesNotificationProviderAdapterTest.java:50 .../twilio/TwilioSmsProviderAdapterTest.java:24 .../apns/ApnsNotificationProviderAdapterTest.java:31 ``` **8종 중 3종.** 클래스 javadoc은 "Subclasses supply an adapter and a fault harness; the assertions are here **so that a new provider cannot be added without answering the same three questions**"라고 쓰지만, 상속을 강제하는 장치는 없다. ## 같은 종류의 강제가 다른 곳에는 있다 이 저장소는 같은 종류의 강제를 다른 곳에서는 만들어 두었다 — `EndpointGuardCallSiteTest`(가드가 호출처에서 실제로 도달하는가), `verifyNotificationApiSurface`(공개 타입 586개 스냅샷 고정). 여기에는 없다. ## EndpointGuardCallSiteTest 참조 위치 :::evidence key="adapter-outbound-notification-c06" alt="코드베이스에서 EndpointGuardCallSiteTest 를 검색한 출력 1줄. 이 기록이 세는 참조가 그 출력에 그대로 보인다." caption="EndpointGuardCallSiteTest 코드베이스 검색 — 1줄 · exit 0" zoom="true" ::: ## 크로스-프로바이더 스위트에 등록된 다섯 `ContractAdapters`가 크로스-프로바이더 스위트에 등록하는 것은 **5종**(ses · twilio · apns · webpush · webhook)이다. 빠진 둘은 fcm과 smtp이고, 그것은 harness의 구조적 한계로 설명된다 — 스위트는 HTTP 루프백 서버 위에서 돌고, SMTP는 JavaMail 릴레이로, FCM은 `FcmGateway` 심으로 나간다.