Files
clean-architecture-backend-…/src/adapter/outbound/persistence-mongo
DongHyeonkaandClaude Opus 5 d57d2f62a0 feat(mongodb): implement the MongoDB document persistence platform
Implements the mongodb-superpowers-package design: Stable Tasks 1-50 and
Advanced Tasks 1-15.

The design assumes 19 Stable + 12 Advanced Gradle projects under
modules/mongodb*. This repository's fail-closed registry declares exactly 19
leaf identities, so those modules become package boundaries inside the
registered leaf :adapter:outbound:persistence-mongo, with the design's module
dependency table enforced by ten ArchUnit rules. The mapping and every
deviation are recorded in docs/mongodb/repository-adaptation.md.

Contract highlights, all enforced by tests rather than convention:

- Transaction body retry and commit retry are separate loops. A new session per
  body attempt; commit-only retry on an unknown commit. The body is never
  replayed after a commit ambiguity, so a failover cannot become a duplicate.
- MongoExecutionOutcome keeps both ambiguous outcomes distinct from success and
  failure, and MongoFailureContext records only the design-permitted fields.
- Failure classification reads server error labels before numeric codes.
- BSON representations come from a pinned manifest, never a library default,
  and a golden type-signature gate fails on any drift.
- Index and validator changes go through the manifest and the admin plane;
  metadata ownership gates every drop.
- Every Advanced capability refuses construction unless its flag is enabled.

Verified against real servers, not only unit tests. Running the lanes for the
first time exposed four defects that a green `check` had hidden:

- Four release lanes passed while executing zero tests; the gate now counts
  executed tests per lane and fails on zero.
- The "single replica set" fixture was a standalone, because Testcontainers 2.x
  needs withReplicaSet(); its test only asserted a connection string.
- The three-node fixture was three independent clusters, so no election could
  occur, and awaitNewPrimary() compared against the post-stop primary.
- The migration lease checked modifiedCount, so a same-millisecond refresh read
  as a lost lease.

scripts/verify-mongodb-platform.sh now reports:
  9 lanes, 0 skipped, 0 failed, every evidence category produced.

scripts/verify-mongodb-advanced.sh reports NOT PROMOTABLE: actual-topology
evidence (real sharded cluster, real KMS, real target deployment) is
unobtainable here, so it is named rather than assumed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-14 13:41:00 +09:00
..

adapter:outbound:persistence-mongo

dev.caskeleton.adapter.outbound.mongo 패키지의 opt-in MongoDB Document Persistence Platform이다. 템플릿 production 코드에 가짜 비즈니스 Example* 타입을 두지 않고, 실제 프로젝트가 자신의 document/repository/mapper와 application 또는 domain port 구현을 추가할 수 있는 구성 경계와 플랫폼 정책을 제공한다.

설계 원본은 mongodb-superpowers-package/docs/superpowers/specs/이고, 이 저장소로 어떻게 매핑했는지는 docs/mongodb/repository-adaptation.md가 단일 기록이다.

활성화

기본값은 비활성이다.

ca-skeleton.persistence-mongo.enabled=true
spring.data.mongodb.uri=mongodb://localhost:27017/portfolio

활성화 시 MongoPersistenceConfig가 Spring Boot의 Mongo client 및 data auto-configuration을 명시적으로 가져와 MongoClientMongoTemplate을 구성하고, MongoPlatformAutoConfiguration이 플랫폼 정책 bean(startup validator, client generation registry, health indicator)을 등록한다. repository scanning은 템플릿이 임의로 소유하지 않는다. 실제 consumer가 자신의 repository package와 composition을 명시해야 한다.

Mongo starter는 classpath만으로도 Boot auto-configuration 후보를 등록하므로 config의 조건만으로는 기본 비활성을 보장할 수 없다. MongoOptInAutoConfigurationImportFilter가 Boot 4의 sync/reactive client, data, repository, health, metrics Mongo auto-configuration을 default/false에서 후보군에서 제외한다. 필터는 Boot 4가 AutoConfigurationImportFilter를 찾는 META-INF/spring.factories에 등록되어 있으며, enabled=true일 때는 후보를 그대로 허용한다.

MongoPersistenceProperties는 모듈 opt-in만 소유한다. URI, database, credential은 Spring의 표준 spring.data.mongodb.* 설정을 사용한다. 플랫폼 profile은 ca-skeleton.persistence-mongo.platform.* (MongoPlatformProperties)이 소유한다.

노출 계층 (D1D4)

계층 내용 Client
D1 표준 document 영속성 Spring Data repository, typed query, mapping manifest, atomic update, optimistic revision Stable API V1 strict
D2 고급 document 연산 MongoTemplate, transaction/session, bulk, aggregation, keyset cursor, change stream Stable API V1 strict
D3 명시적 capability native BSON, time series, search/vector, CSFLE/QE, shard-aware capability client
D4 admin plane collection, validator, index, migration, shard, repair admin client + 별도 credential

D3는 raw client escape가 아니다. PolicyAwareMongoNativeGateway가 capability → database profile → collection allowlist → operation name → timeout → consistency → result limit → trace → redaction → command category → D4 차단 순서를 고정한다.

패키지 지도

패키지 책임
api (+ capability, consistency, error, mapping, observation, profile, schema) framework 없는 core 계약. Spring/driver/BSON/Reactor import 금지 (ArchUnit)
mapping (+ type), failure Spring Data 통합, BSON 표현 manifest, 실패 분류·변환
imperative (+ atomic, bulk, revision) 명령형 실행, update operator, bulk 부분 결과, optimistic revision
reactive (+ cursor) 반응형 실행, cursor lease/guard
query (+ budget, pagination) query guardrail, operation budget, keyset pagination
aggregation 등록된 pipeline plan과 risk 등급
transaction (+ retry, session) transaction 실행, body/commit 분리 retry, causal session
schema (+ index, manifest, model, ttl, validation) document model·index·validator manifest와 diff/apply, TTL 정책
changestream (+ projector, recovery) at-least-once projector, resume checkpoint, history-lost 처리
geo GeoJSON / 2dsphere
migration (+ flamingock) checksum·lock·precondition 기반 migration runner
observation driver-native command/pool/SDAM 관측, tag allowlist, redaction
security (+ admin), nativecap 역할·credential·TLS profile, admin plane, native capability gateway
autoconfigure Boot auto-configuration, startup validation, client generation, release gate
advanced/** opt-in Advanced/Experimental capability (sharding, time series, CSFLE, QE, search, vector, tenancy, bridge, GridFS)
architecture fork가 자기 코드에 적용하는 @MongoOperation marker와 ArchUnit rule set

의존성 경계

  • production project dependency 없음
  • Spring Boot MongoDB starter(sync/reactive), configuration processor, Micrometer, SLF4J만 사용
  • JPA persistence adapter 및 다른 adapter와 의존 관계 없음
  • idempotency, outbox, distributed lock은 기존 JPA adapter 책임을 유지
  • 패키지 간 방향은 MongoModuleBoundaryTest(ArchUnit) 10개 규칙이 강제한다: core-api는 framework 무의존, Stable은 Advanced에 의존 금지, production은 testkit에 의존 금지, imperative↛reactive, query↛aggregation, schema↛execution, observability↛execution, migration↛flamingock

테스트 lane

Task 내용 Docker
test 단위 + hermetic contract (Docker tag 제외) 불필요
mongoStableContractTest mongodb-contract 태그. check에 포함 불필요
mongoReplicaSetTest single-node replica set 필요
mongoFailoverTest 3-node set + Toxiproxy 필요
mongoMigrationTest migration/backfill 재시작 필요
mongoCompatibilityTest MongoDB 7.0 lane 필요
mongoSecurityIntegrationTest credential/TLS/회전 필요
mongoPerformanceTest 자원 budget과 chaos gate 필요

이미지는 고정되어 있다: mongo:8.0.16(primary), mongo:7.0.28(compatibility), ghcr.io/shopify/toxiproxy:2.12.0. -PmongoPrimaryImage= 등으로 재정의할 수 있다.

검증

cd src
./gradlew :adapter:outbound:persistence-mongo:check --console=plain

릴리스 게이트는 저장소 루트에서 실행한다.

bash scripts/verify-mongodb-platform.sh
bash scripts/verify-mongodb-advanced.sh

문서