Skip to content

Gseobi/commerce-orchestration-backend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

72 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

commerce-orchestration-backend

Spring Boot ๊ธฐ๋ฐ˜ commerce orchestration backend์ž…๋‹ˆ๋‹ค.

์ด ํ”„๋กœ์ ํŠธ๋Š” ์ปค๋จธ์Šค ์ฃผ๋ฌธ API ์ž์ฒด๋ณด๋‹ค, ์ฃผ๋ฌธ ์ดํ›„ ์ด์–ด์ง€๋Š” payment ยท settlement ยท notification ยท outbox publish ํ๋ฆ„์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ƒํƒœ ๋ถˆ์ผ์น˜, ์‹คํŒจ ๋ถ„๊ธฐ, ๋ณต๊ตฌ ๊ฒฝ๋กœ๋ฅผ ์–ด๋–ป๊ฒŒ ์ œ์–ดํ•  ๊ฒƒ์ธ๊ฐ€์— ์ดˆ์ ์„ ๋‘ก๋‹ˆ๋‹ค.

์ฃผ๋ฌธ ์ดํ›„ ํ›„์† ์ฒ˜๋ฆฌ๋ฅผ ๋‹จ์ˆœ ์ˆœ์ฐจ ํ˜ธ์ถœ๋กœ ํฉ๋ฟŒ๋ฆฌ์ง€ ์•Š๊ณ , CommerceOrchestrationService๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ๋ช…์‹œ์  ์ƒํƒœ ์ „์ด, failure branching, compensation, retry/dead-letter, admin reprocessing ํ๋ฆ„์œผ๋กœ ์ถ”์  ๊ฐ€๋Šฅํ•˜๊ฒŒ ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ ˆํฌ๋Š” pinned ๋Œ€ํ‘œ ํฌํŠธํด๋ฆฌ์˜ค ๋ ˆํฌ๋กœ, "์ปค๋จธ์Šค ๊ฑฐ๋ž˜ ํ๋ฆ„์—์„œ ์ƒํƒœยท์ •ํ•ฉ์„ฑยท์‹คํŒจ ๋ณต๊ตฌ๋ฅผ ์–ด๋–ป๊ฒŒ ์„ค๊ณ„ํ–ˆ๊ณ , ์–ด๋””๊นŒ์ง€ ๊ฒ€์ฆํ–ˆ๋Š”๊ฐ€"๋ฅผ ์งง์€ ์‹œ๊ฐ„ ์•ˆ์— ์ดํ•ด์‹œํ‚ค๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ํฌ์ธํŠธ๋Š” ์„ธ ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

  • ๋ฌด์—‡์„ ์ œ์–ดํ•˜๋‚˜:
    order ์ดํ›„ payment, settlement, notification, outbox publish๋ฅผ ํ•˜๋‚˜์˜ orchestration ํ๋ฆ„์œผ๋กœ ์ œ์–ดํ•˜๊ณ , ๊ฐ ๋‹จ๊ณ„์˜ ์ƒํƒœ ์ „์ด์™€ ์‹คํŒจ ์ง€์ ์„ ๋ฐ์ดํ„ฐ๋กœ ๋‚จ๊น๋‹ˆ๋‹ค.
  • ๋ฌด์—‡์„ ์ฆ๋ช…ํ•˜๋‚˜:
    ์ปค๋จธ์Šค ๊ฑฐ๋ž˜ ํ๋ฆ„์—์„œ ์ค‘์š”ํ•œ explicit state transition, failure branching, compensation, retry/dead-letter, admin reprocessing, Modulith boundary, Flyway + integration-test ๊ธฐ์ค€์„ ์„ ํ•จ๊ป˜ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
  • ์–ด๋””๋ฅผ ๋ณด๋ฉด ๋˜๋‚˜:
    ๋จผ์ € ์ด README์—์„œ ์ „์ฒด ๋ฌธ์ œ ์ •์˜์™€ ๊ฒ€์ฆ ๋ฒ”์œ„๋ฅผ ๋ณด๊ณ , ์ด์–ด์„œ Docs Index, Architecture Notes, Flow Notes๋ฅผ ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ด ๋ ˆํฌ๋Š” CRUD ํ™”๋ฉด ์ˆ˜๋‚˜ ์—”๋“œํฌ์ธํŠธ ์ˆ˜๋ณด๋‹ค ์•„๋ž˜๋ฅผ ๋จผ์ € ์ฆ๋ช…ํ•˜๋Š” ๋ฐ ์ดˆ์ ์„ ๋‘ก๋‹ˆ๋‹ค.

  • CommerceOrchestrationService๋ฅผ ์ค‘์‹ฌ์œผ๋กœ order lifecycle๊ณผ ํ›„์† ๊ฑฐ๋ž˜ ํ๋ฆ„์„ ๋ช…์‹œ์ ์œผ๋กœ ์ œ์–ดํ•˜๋Š” ๊ฒƒ
  • ์ƒํƒœ ์ „์ด, ์‹คํŒจ ๋ถ„๊ธฐ, ์šด์˜ ๋ณต๊ตฌ ์ง€์ ์„ order status, orchestration step, outbox event, notification event, audit log๋กœ ๋‚จ๊ธฐ๋Š” ๊ฒƒ
  • settlement ์‹คํŒจ์™€ notification ์‹คํŒจ๋ฅผ ๊ฐ™์€ ์˜ค๋ฅ˜๋กœ ๋ญ‰๊ฐœ์ง€ ์•Š๊ณ , ์„œ๋กœ ๋‹ค๋ฅธ ๋ณด์ƒ / ์žฌ์ฒ˜๋ฆฌ / ๋ฌด์‹œ ๊ฐ€๋Šฅ ์‹คํŒจ ์ •์ฑ…์œผ๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ
  • outbox retry/dead-letter์™€ notification retry/manual intervention ํ๋ฆ„์„ ํ†ตํ•ด ์‹คํŒจ ํ›„ ๋ณต๊ตฌ ๊ฐ€๋Šฅํ•œ ์šด์˜ ์ง€์ ์„ ๋“œ๋Ÿฌ๋‚ด๋Š” ๊ฒƒ
  • Spring Modulith ๊ธฐ์ค€์œผ๋กœ module boundary๋ฅผ ๊ฒ€์ฆํ•˜๊ณ , Testcontainers ๊ธฐ๋ฐ˜ integration test๋กœ ์‹ค์ œ ํ๋ฆ„์„ ํ™•์ธํ•˜๋Š” ๊ฒƒ

1. Start Here

์ฒ˜์Œ ๋ณด๋Š” ์‚ฌ๋žŒ ๊ธฐ์ค€ ๊ถŒ์žฅ ์ฝ๊ธฐ ์ˆœ์„œ๋Š” ์•„๋ž˜์ž…๋‹ˆ๋‹ค.

  1. ๋ฌธ์„œ ๊ตฌ์กฐ: Docs Index
  2. Modulith / ํŒจํ‚ค์ง€ ๊ตฌ์กฐ: Architecture Notes
  3. Order / Payment / Settlement ํ๋ฆ„: Flow Notes
  4. ๊ธฐ์ˆ  ์„ ํƒ ๊ทผ๊ฑฐ: Technical Decisions
  5. ๊ธฐ์ˆ  ๊ฒ€ํ†  ํฌ์ธํŠธ: Technical Discussion Points
  6. ์„ค๊ณ„ ๊ฒฐ์ •๊ณผ Trade-off: Design Notes
  7. ๊ตฌํ˜„ ๊ฒ€ํ†  / Boundary ํŒ๋‹จ: Implementation Review Notes
  8. ๊ตฌํ˜„-๊ฒ€์ฆ ๋งคํ•‘: Verification Matrix
  9. AI-assisted ๊ฒ€์ฆ ๊ธฐ์ค€: AI-assisted Development & Verification / Claim Audit
  10. Future Scope ์„ค๊ณ„: Payment Timeout Confirmation Flow / Provider Callback Flow Review
  11. ์šด์˜ ๊ด€์ธก์„ฑ: Observability Alert Candidates & Metric Naming
  12. OpenAPI / ApiDog: OpenAPI Spec / OpenAPI Guide
  13. ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ / ์ด์Šˆ ๋Œ€์‘: Test Report / Troubleshooting

ํ”„๋กœ์ ํŠธ ์„ค๊ณ„ ์˜๋„์™€ ๊ตฌํ˜„ ๋ฒ”์œ„๋Š” Velog ๊ธ€์—์„œ๋„ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

draw.io ์ž์‚ฐ์€ Diagram Guide ๊ธฐ์ค€์œผ๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
ํ˜„์žฌ overall architecture๋Š” README ๋Œ€ํ‘œ ์ด๋ฏธ์ง€๋กœ๋งŒ ์œ ์ง€ํ•˜๊ณ , ์„ธ๋ถ€ ํ๋ฆ„๊ณผ ํ…Œ์ด๋ธ” ๊ด€๊ณ„๋Š” Architecture Notes / Flow Notes / Diagram Guide์—์„œ ์ด์–ด์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Diagram Snapshot

์ด ๊ทธ๋ฆผ์€ ํ˜„์žฌ ๊ตฌํ˜„ ๊ธฐ์ค€์˜ overall architecture๋ฅผ ํ•œ ์žฅ์œผ๋กœ ์š”์•ฝํ•œ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์ž…๋‹ˆ๋‹ค.

Overall architecture

Diagrams

์ด ํ”„๋กœ์ ํŠธ์˜ ์ฃผ์š” ํ๋ฆ„๊ณผ ์ตœ๊ทผ reliability hardening ์ž‘์—…์€ ์•„๋ž˜ ๋‹ค์ด์–ด๊ทธ๋žจ์œผ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

Diagram Purpose
Overall Architecture ์ฃผ๋ฌธ ์ดํ›„ payment, settlement, notification, outbox ํ๋ฆ„์˜ ์ „์ฒด ๊ตฌ์กฐ
Notification Recovery Flow notification ์‹คํŒจ ์ดํ›„ retry/manual intervention ํ๋ฆ„
Outbox Retry / Dead Letter outbox publish ์‹คํŒจ ์ดํ›„ retry/dead-letter ํ๋ฆ„
Reliability Hardening Overview payment idempotency, retry claim, publisher adapter ๋ณด๊ฐ• ์š”์•ฝ
Payment Idempotency Flow paymentRequestId ๊ธฐ๋ฐ˜ ์ค‘๋ณต ๊ฒฐ์ œ ์š”์ฒญ ์ œ์–ด
Notification / Outbox Processing Claim Flow PROCESSING claim ๊ธฐ๋ฐ˜ ์ค‘๋ณต ์žฌ์ฒ˜๋ฆฌ ์ œ์–ด
Outbox Publisher Adapter Outbox ์ƒํƒœ ๊ด€๋ฆฌ์™€ Kafka ๋ฐœํ–‰ ๊ตฌํ˜„ ๋ถ„๋ฆฌ

Reliability hardening overview


2. Snapshot

  • ์—ญํ• :
    ์ฃผ๋ฌธ ์ƒ์„ฑ ์ดํ›„ payment, settlement, notification, outbox publish๋ฅผ orchestration ๊ด€์ ์—์„œ ์ œ์–ดํ•˜๋Š” backend
  • ํ•ต์‹ฌ ๋ฌธ์ œ:
    ๊ฒฐ์ œ ์„ฑ๊ณต ์ดํ›„ ์ •์‚ฐ ์‹คํŒจ, ์•Œ๋ฆผ ์‹คํŒจ, ์ด๋ฒคํŠธ ๋ฐœํ–‰ ์‹คํŒจ์ฒ˜๋Ÿผ ์ผ๋ถ€ ํ›„์† ์ฒ˜๋ฆฌ๋งŒ ์‹คํŒจํ–ˆ์„ ๋•Œ ๋‚ด๋ถ€ ์ƒํƒœ๋ฅผ ์–ด๋–ป๊ฒŒ ๋‚จ๊ธฐ๊ณ  ๋ณต๊ตฌํ•  ๊ฒƒ์ธ๊ฐ€
  • ๊ฐ•์ :
    explicit state transition, compensation ๋ถ„๋ฆฌ, notification retry/manual/ignore ์ •์ฑ…, outbox retry/dead-letter, admin reprocessing, idempotency/claim ๊ธฐ๋ฐ˜ reliability hardening
  • ๊ฑฐ๋ž˜/์—ฐ๋™ ๊ด€์ :
    ์™ธ๋ถ€ payment provider ์—ฐ๋™ ๊ณจ๊ฒฉ, settlement failure compensation, outbox ๊ธฐ๋ฐ˜ ํ›„์† publish ๋ถ„๋ฆฌ๋ฅผ ํ†ตํ•ด ๊ฑฐ๋ž˜ ํ๋ฆ„์˜ ์ •ํ•ฉ์„ฑ๊ณผ ๋ณต๊ตฌ ๊ฐ€๋Šฅ์„ฑ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
  • ๋ชจ๋“ˆ ๊ตฌ์กฐ:
    Spring Modulith ๊ธฐ๋ฐ˜์œผ๋กœ *.api ๊ณต๊ฐœ ๊ณ„์•ฝ๊ณผ ApplicationModules.verify() ๊ฒ€์ฆ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ์˜์กด์„ฑ ์ƒํƒœ:
    ํ˜„์žฌ build.gradle์€ ๊ฒ€์ฆ๋œ ๊ตฌํ˜„ ๋ฒ”์œ„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ฆฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
    Spring MVC + WebClient + Security + JPA/Flyway + Kafka + Modulith + Testcontainers ์กฐํ•ฉ์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • ํ˜„์žฌ ๋กœ์ปฌ ๊ฒ€์ฆ:
    ./gradlew clean test --rerun-tasks,
    ./gradlew clean integrationTest --rerun-tasks --stacktrace ๊ธฐ์ค€ ํ†ต๊ณผ
  • ํ˜„์žฌ CI ์ƒํƒœ:
    GitHub Actions๋Š” build-and-test, integration-test ๋‘ job์œผ๋กœ ์œ ์ง€ ์ค‘์ด๋ฉฐ, compile/test/integration ๊ฒ€์ฆ ์˜๋ฏธ๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

3. ์ด ๋ ˆํฌ๊ฐ€ ํ˜„์žฌ ์ฆ๋ช…ํ•˜๋Š” ๊ฒƒ

  • ์ฃผ๋ฌธ ์ดํ›„ ํ›„์† ์ž‘์—…์„ controller ๋‹จ์œ„๋กœ ํฉ๋ฟŒ๋ฆฌ์ง€ ์•Š๊ณ  orchestration service์—์„œ ํ๋ฆ„ ์ค‘์‹ฌ์œผ๋กœ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.
  • ์ฃผ๋ฌธ ์ƒํƒœ ์ „์ด๋Š” ๋ฌต์‹œ์  ์ฒ˜๋ฆฌ ๋Œ€์‹  ๋ช…์‹œ์  ์ƒํƒœ ๋ณ€๊ฒฝ์œผ๋กœ ๊ธฐ๋ก๋ฉ๋‹ˆ๋‹ค.
  • payment / settlement / notification / outbox ์‹คํŒจ๋ฅผ ์„œ๋กœ ๋‹ค๋ฅธ ์ •์ฑ…์œผ๋กœ ๋ถ„๊ธฐํ•ฉ๋‹ˆ๋‹ค.
  • paymentRequestId ๊ธฐ์ค€ ๊ฒฐ์ œ ๋ฉฑ๋“ฑ์„ฑ์œผ๋กœ ๋™์ผ ์Šน์ธ ์š”์ฒญ replay ์‹œ provider ์ค‘๋ณต ํ˜ธ์ถœ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • settlement ์‹คํŒจ๋Š” payment cancel compensation ํ๋ฆ„์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • notification ์‹คํŒจ๋Š” AUTO_RETRY, MANUAL_INTERVENTION, IGNORE ์ •์ฑ…์œผ๋กœ ๋ถ„๊ธฐํ•ฉ๋‹ˆ๋‹ค.
  • RETRY_SCHEDULED notification event๋Š” PROCESSING claim ์ดํ›„ due processor๋ฅผ ํ†ตํ•ด ์žฌ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • outbox๋ฅผ ํ†ตํ•ด ํ›„์† ์ด๋ฒคํŠธ ๋ฐœํ–‰์„ ๋ถ„๋ฆฌํ•˜๊ณ , READY / RETRY_WAIT event๋ฅผ PROCESSING์œผ๋กœ ์„ ์ ํ•œ ๋’ค publishํ•ฉ๋‹ˆ๋‹ค.
  • Outbox ์ƒํƒœ ๊ด€๋ฆฌ์™€ Kafka ๋ฐœํ–‰ ๊ตฌํ˜„์„ OutboxEventPublisher adapter๋กœ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์šด์˜์ž๋Š” ์ „์ฒด orchestration ์žฌ์‹คํ–‰์ด ์•„๋‹ˆ๋ผ ์‹คํŒจํ•œ ํ•˜์œ„ ์ฒ˜๋ฆฌ ๋‹จ์œ„๋ฅผ admin ์žฌ์ฒ˜๋ฆฌ API๋กœ ๋ณต๊ตฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Spring Modulith ๊ธฐ์ค€์œผ๋กœ domain module์˜ ๊ณต๊ฐœ API์™€ ๋‚ด๋ถ€ ๊ตฌํ˜„ ๊ฒฝ๊ณ„๋ฅผ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
  • Testcontainers ๊ธฐ๋ฐ˜ PostgreSQL / Kafka integration test๋กœ ์ฃผ์š” ์ƒํƒœ ์ „์ด์™€ ๋ณต๊ตฌ ํ๋ฆ„์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.

Reliability Hardening

์ตœ๊ทผ ๋ณด๊ฐ•์—์„œ๋Š” ์ฃผ๋ฌธ ์ดํ›„ ํ๋ฆ„์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ค‘๋ณต ์š”์ฒญ๊ณผ ์žฌ์ฒ˜๋ฆฌ ๋™์‹œ ์‹คํ–‰ ๊ฐ€๋Šฅ์„ฑ์„ ์ค„์ด๊ธฐ ์œ„ํ•ด paymentRequestId ๊ธฐ๋ฐ˜ ๊ฒฐ์ œ ๋ฉฑ๋“ฑ์„ฑ, notification/outbox PROCESSING claim, Outbox publisher adapter ๋ถ„๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

  • Payment Idempotency: ๊ฐ™์€ paymentRequestId๋กœ ์Šน์ธ ์š”์ฒญ์ด ๋ฐ˜๋ณต๋˜๋ฉด provider๋ฅผ ๋‹ค์‹œ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  ๊ธฐ์กด payment ๊ธฐ์ค€ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • Notification Retry Claim: due RETRY_SCHEDULED event๋ฅผ PROCESSING์œผ๋กœ ์„ ์ ํ•œ ์‹คํ–‰์ž๋งŒ retry ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ , ์„ ์  ์‹คํŒจ๋Š” skipped๋กœ ์ง‘๊ณ„ํ•ฉ๋‹ˆ๋‹ค.
  • Outbox Publisher Adapter: OutboxPublisherService๋Š” retry/dead-letter ์ƒํƒœ ์ „์ด๋งŒ ๋‹ด๋‹นํ•˜๊ณ , Kafka ๋ฐœํ–‰์€ KafkaOutboxEventPublisher๊ฐ€ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
  • Outbox Publish Claim: READY / RETRY_WAIT event๋ฅผ PROCESSING์œผ๋กœ ์„ ์ ํ•œ ๋’ค publishํ•ด ์ค‘๋ณต ๋ฐœํ–‰ ๊ฐ€๋Šฅ์„ฑ์„ ์ค„์ž…๋‹ˆ๋‹ค.

Observability & Recovery Notes

  • Outbox publish, notification retry, admin recovery ๊ฒฝ๊ณ„์— Micrometer counter์™€ key-value structured log๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ „์ฒด ๊ด€์ธก/๋ณต๊ตฌ ํ๋ฆ„์€ Observability Recovery Architecture Diagram์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ด ์ง€ํ‘œ์™€ ๋กœ๊ทธ๋Š” retry/dead-letter ์ฆ๊ฐ€, claim skipped, admin recovery ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ ์šด์˜ ๊ด€์ธก์„ฑ ๊ธฐ์ค€์ž…๋‹ˆ๋‹ค.
  • alert ํ›„๋ณด์™€ metric tag ๊ธฐ์ค€์€ Observability Alert Candidates & Metric Naming์— ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. Prometheus/Grafana dashboard์™€ alert rule ๊ตฌํ˜„์€ Future Scope์ž…๋‹ˆ๋‹ค.
  • ์ž์„ธํ•œ ๋ณต๊ตฌ ์ ˆ์ฐจ๋Š” Admin Recovery Runbook์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

4. ๋ฌธ์ œ ์ •์˜

์ปค๋จธ์Šค ์ฃผ๋ฌธ ์ดํ›„์—๋Š” ๊ฒฐ์ œ ์Šน์ธ, ์ •์‚ฐ ์š”์ฒญ, ์•Œ๋ฆผ ๋ฐœ์†ก, ์ด๋ฒคํŠธ ๋ฐœํ–‰, ์‹คํŒจ ๋ณต๊ตฌ๊ฐ€ ์ด์–ด์ง‘๋‹ˆ๋‹ค.

์‹ค์ œ ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” ๋ชจ๋“  ํ›„์† ์ฒ˜๋ฆฌ๊ฐ€ ํ•œ ๋ฒˆ์— ์„ฑ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ฒฐ์ œ๋Š” ์„ฑ๊ณตํ–ˆ์ง€๋งŒ ์ •์‚ฐ ์š”์ฒญ์ด ์‹คํŒจํ•˜๊ฑฐ๋‚˜, ๊ฑฐ๋ž˜ ์ž์ฒด๋Š” ์™„๋ฃŒ๋์ง€๋งŒ ์•Œ๋ฆผ ๋ฐœ์†ก ๋˜๋Š” ํ›„์† ์ด๋ฒคํŠธ ๋ฐœํ–‰๋งŒ ์‹คํŒจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ ์ค‘์š”ํ•œ ๋ฌธ์ œ๋Š” ๋‹จ์ˆœ rollback์ด ์•„๋‹ˆ๋ผ, ์–ด๋А ๋‹จ๊ณ„๊นŒ์ง€ ์„ฑ๊ณตํ–ˆ๋Š”์ง€, ์–ด๋””์„œ ์‹คํŒจํ–ˆ๋Š”์ง€, ์–ด๋–ค ๋‹จ์œ„๋กœ ์žฌ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ๋ช…ํ™•ํžˆ ๋‚จ๊ธฐ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ๋ ˆํฌ๋Š” ์ฃผ๋ฌธ ์ดํ›„ ํ›„์† ํ๋ฆ„์„ ์—ฌ๋Ÿฌ controller์™€ ad-hoc service ํ˜ธ์ถœ์— ๋ถ„์‚ฐ์‹œํ‚ค์ง€ ์•Š๊ณ , ๋ช…์‹œ์  ์ƒํƒœ ์ „์ด์™€ ์šด์˜ ๋ณต๊ตฌ ๊ฒฝ๋กœ๊ฐ€ ๋ณด์ด๋Š” orchestration backend๋กœ ์ •๋ฆฌํ•˜๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ ๊ธฐ์ค€์„ ์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ๋น„์ฆˆ๋‹ˆ์Šค ์™ธ๋ถ€ ์ง„์ž…์ ์€ OrderController์ž…๋‹ˆ๋‹ค.
  • ์ธ์ฆ์šฉ AuthController๋Š” ๋ฐ๋ชจ JWT ๋ฐœ๊ธ‰ ๋ณด์กฐ ์—”๋“œํฌ์ธํŠธ๋งŒ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • CommerceOrchestrationService๋Š” ์ฃผ๋ฌธ ์ดํ›„ ํ๋ฆ„ ์ œ์–ด๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
  • NotificationRetryProcessor๋Š” RETRY_SCHEDULED notification event์˜ due retry ์ฒ˜๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
  • payment, settlement, notification, outbox, audit๋Š” ๊ฐ์ž ์ž๊ธฐ repository๋ฅผ ๋‚ด๋ถ€ service๊ฐ€ ์†Œ์œ ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฒฐ์ œ provider๋Š” PaymentProviderClient ์ธํ„ฐํŽ˜์ด์Šค ์•„๋ž˜ mock / external ๊ตฌํ˜„์œผ๋กœ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • outbox๋Š” READY / RETRY_WAIT -> PROCESSING -> PUBLISHED / RETRY_WAIT / DEAD_LETTER ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • settlement ์‹คํŒจ์™€ notification ์‹คํŒจ๋Š” ๋™์ผ ๋ณด์ƒ ์ •์ฑ…์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • admin์€ notification-events, outbox-events ๋‹จ์œ„๋กœ ๋ช…์‹œ์  ์žฌ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • DB ์Šคํ‚ค๋งˆ์˜ source of truth๋Š” Flyway migration์ž…๋‹ˆ๋‹ค.

5. ํ•ต์‹ฌ ์„ค๊ณ„

Business Flow

  1. POST /api/orders๋กœ ์ฃผ๋ฌธ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  2. POST /api/orders/{orderId}/orchestrate๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด orchestration์ด ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.
  3. payment ์Šน์ธ ํ›„ ์ฃผ๋ฌธ์„ PAID๋กœ ์ „์ดํ•ฉ๋‹ˆ๋‹ค.
  4. settlement ์š”์ฒญ ํ›„ ์ฃผ๋ฌธ์„ SETTLEMENT_REQUESTED๋กœ ์ „์ดํ•˜๊ณ  outbox event๋ฅผ ๋‚จ๊น๋‹ˆ๋‹ค.
  5. notification ์š”์ฒญ ํ›„ ์ฃผ๋ฌธ์„ NOTIFICATION_REQUESTED๋กœ ์ „์ดํ•˜๊ณ  outbox event๋ฅผ ๋‚จ๊น๋‹ˆ๋‹ค.
  6. ์ตœ์ข…์ ์œผ๋กœ COMPLETED, ๋˜๋Š” ์‹คํŒจ ๋ถ„๊ธฐ์— ๋”ฐ๋ผ FAILED / CANCELLED๋กœ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

Module Intent

  • order
    ์ฃผ๋ฌธ ์ƒ์„ฑ, ์ƒํƒœ ์ „์ด, ์™ธ๋ถ€ ๋น„์ฆˆ๋‹ˆ์Šค ์ง„์ž… facade
  • orchestration
    ํ๋ฆ„ ์ œ์–ด, orchestration step ๊ธฐ๋ก, notification retry processor ์กฐํ•ฉ
  • payment
    ๊ฒฐ์ œ ์Šน์ธ/์ทจ์†Œ์™€ provider ์—ฐ๋™ ์ถ”์ƒํ™”
  • settlement
    ์ •์‚ฐ ์š”์ฒญ ๊ธฐ๋ก
  • notification
    ์•Œ๋ฆผ ์š”์ฒญ ๊ธฐ๋ก, ์‹คํŒจ ์ •์ฑ…, retry ์ƒํƒœ ๊ด€๋ฆฌ
  • outbox
    ์ด๋ฒคํŠธ ์ €์žฅ, ์žฌ์‹œ๋„, publish, dead-letter ์ „ํ™˜
  • audit
    ๋ถ„๊ธฐ/์žฌ์‹คํ–‰/์‹คํŒจ ๊ธฐ๋ก
  • admin
    notification / outbox ์šด์˜ ์žฌ์ฒ˜๋ฆฌ API
  • common
    ๊ณตํ†ต ์‘๋‹ต, ์˜ˆ์™ธ, ๊ณตํ†ต ๊ธฐ๋ฐ˜ ํƒ€์ž…

Dependency Direction

  • controller -> facade/service -> repository
  • orchestration -> domain application contract
  • ๋‹ค๋ฅธ domain์˜ repository๋ฅผ ์ง์ ‘ ์ฃผ์ž…ํ•ด์„œ ํ๋ฆ„์„ ์ œ์–ดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • repository ํŒจํ‚ค์ง€๋ฅผ ์™ธ๋ถ€์— ๊ณต๊ฐœํ•˜๋Š” ๋ฐฉ์‹๋ณด๋‹ค *.api ๊ณต๊ฐœ ๊ณ„์•ฝ์„ ํ†ตํ•ด ํ˜‘๋ ฅํ•˜๋Š” ๋ฐฉ์‹์„ ์šฐ์„ ํ•ฉ๋‹ˆ๋‹ค.
  • Spring Modulith์˜ @NamedInterface("api")์™€ allowedDependencies๋ฅผ ํ†ตํ•ด module boundary๋ฅผ ๋ช…์‹œํ•ฉ๋‹ˆ๋‹ค.

์™œ ์ด๋Ÿฐ ๊ตฌ์กฐ๋ฅผ ํƒํ–ˆ๋Š”๊ฐ€

  • ์ฃผ๋ฌธ ์ดํ›„ ๊ฑฐ๋ž˜ ํ๋ฆ„์€ payment, settlement, notification, outbox publish์ฒ˜๋Ÿผ ์„œ๋กœ ๋‹ค๋ฅธ ์‹คํŒจ ๊ฐ€๋Šฅ์„ฑ๊ณผ ๋ณต๊ตฌ ๊ธฐ์ค€์„ ๊ฐ€์ง„ ๋‹จ๊ณ„๋กœ ์ด์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์—, ํ๋ฆ„ ์ œ์–ด๋ฅผ ํ•œ๊ณณ์— ๋ชจ์•„ ๋ถ„๊ธฐ์™€ ์ข…๋ฃŒ ์กฐ๊ฑด์„ ์ฝ๊ธฐ ์‰ฝ๊ฒŒ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • ์ƒํƒœ ์ „์ด์™€ ๋ณด์ƒ ๊ฒฝ๋กœ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๋‚จ๊ฒจ "์–ด๋””๊นŒ์ง€ ์„ฑ๊ณตํ–ˆ๊ณ , ์–ด๋””์„œ ์‹คํŒจํ–ˆ์œผ๋ฉฐ, ์–ด๋–ค ๋‹จ์œ„๋กœ ๋ณต๊ตฌํ•  ์ˆ˜ ์žˆ๋Š”๊ฐ€"๋ฅผ ์ถ”์  ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
  • settlement ์‹คํŒจ๋Š” ๊ฑฐ๋ž˜ ์ •ํ•ฉ์„ฑ์— ์˜ํ–ฅ์„ ์ฃผ๋Š” ์‹คํŒจ๋กœ ๋ณด๊ณ  payment cancel compensation๊นŒ์ง€ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.
  • notification ์‹คํŒจ๋Š” ๊ฑฐ๋ž˜ ์ž์ฒด๋ฅผ ๋˜๋Œ๋ฆด ์‹คํŒจ๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ๋‹จ์ˆœ rollback ๋Œ€์‹  retry / manual intervention / ignore ์ •์ฑ…์œผ๋กœ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • outbox๋ฅผ ๋ณ„๋„ ๊ด€๋ฆฌํ•ด ํ›„์† publish์˜ ์žฌ์‹œ๋„์™€ dead-letter ์ „ํ™˜์„ ๋น„์ฆˆ๋‹ˆ์Šค ์ฒ˜๋ฆฌ์™€ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐ domain์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ์ˆจ๊ธฐ๊ณ , orchestration์€ ๊ณต๊ฐœ๋œ application contract๋งŒ ์กฐํ•ฉํ•˜๋„๋ก ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

6. Payment Provider ๊ตฌ์กฐ

PaymentProviderClient๋Š” ๋‘ ๊ตฌํ˜„ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์„ค์ •์œผ๋กœ ์„ ํƒ๋ฉ๋‹ˆ๋‹ค.

  • mock
    MockPaymentProviderClient
    ๊ธฐ๋ณธ ๋ชจ๋“œ์ž…๋‹ˆ๋‹ค. PAYMENT_PROVIDER_MOCK_FAILURE_TOKEN์ด description์— ํฌํ•จ๋˜๋ฉด ์‹คํŒจ๋ฅผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•ฉ๋‹ˆ๋‹ค. PAYMENT_TIMEOUT_UNKNOWN์ด description์— ํฌํ•จ๋˜๋ฉด ์‹ค์ œ PG ์—ฐ๋™์ด ์•„๋‹Œ mock unknown scenario๋กœ payment๋ฅผ CONFIRMATION_REQUIRED ์ƒํƒœ๋กœ ๋‚จ๊น๋‹ˆ๋‹ค.
  • external
    ExternalPaymentProviderClient
    baseUrl, apiKey, approvePath, cancelPath, connectTimeout, readTimeout๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ external ๊ตฌํ˜„์€ ์‹ค์ œ ์—ฐ๋™์„ ๋ถ™์ผ ์ˆ˜ ์žˆ๋Š” ๊ณจ๊ฒฉ๊ณผ ์˜ค๋ฅ˜ ๋งคํ•‘๊นŒ์ง€ ํฌํ•จํ•˜์ง€๋งŒ, provider๋ณ„ ์ƒ์„ธ error mapping๊ณผ retry policy๋Š” ํ›„์† ๊ณผ์ œ์ž…๋‹ˆ๋‹ค.

๊ฒฐ์ œ ์Šน์ธ ํ๋ฆ„์€ orchestration์—์„œ ์ƒ์„ฑํ•œ deterministic key์ธ "ORDER-" + orderId + "-PAYMENT-APPROVE"๋ฅผ paymentRequestId๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ๊ฐ™์€ ์ฃผ๋ฌธ orchestration replay์—์„œ๋Š” ๋™์ผ key๊ฐ€ ์œ ์ง€๋˜๋ฉฐ, ์ด๋ฏธ ์ €์žฅ๋œ payment๊ฐ€ ์žˆ์œผ๋ฉด provider approve๋ฅผ ๋‹ค์‹œ ํ˜ธ์ถœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. providerTransactionId ์ปฌ๋Ÿผ๊ณผ ์กฐํšŒ ํฌํŠธ๋Š” ์™ธ๋ถ€ callback ๋ฉฑ๋“ฑ์„ฑ ํ™•์žฅ์„ ์œ„ํ•œ ์ค€๋น„ ์ง€์ ์ด๋ฉฐ, callback flow ์ž์ฒด๋Š” ์•„์ง ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.


7. Outbox / Compensation / Recovery ๊ธฐ์ค€

Outbox

  • outbox event๋Š” settlement / notification ํ›„์† publish์šฉ์œผ๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.
  • publisher๋Š” nextAttemptAt์ด ์ง€๋‚œ READY, RETRY_WAIT ์ด๋ฒคํŠธ๋งŒ ๋ฐœํ–‰ ๋Œ€์ƒ์œผ๋กœ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  • ๋ฐœํ–‰ ์ „ DB ์กฐ๊ฑด๋ถ€ update๋กœ PROCESSING ์ƒํƒœ๋ฅผ ์„ ์ ํ•œ ์ด๋ฒคํŠธ๋งŒ publishํ•ฉ๋‹ˆ๋‹ค.
  • ์‹ค์ œ Kafka ๋ฐœํ–‰์€ OutboxEventPublisher ๊ตฌํ˜„์ฒด์ธ KafkaOutboxEventPublisher๊ฐ€ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
  • publish ์‹คํŒจ ์‹œ retryCount, failureCode, failureReason, nextAttemptAt์ด ๊ฐฑ์‹ ๋ฉ๋‹ˆ๋‹ค.
  • maxRetryCount๋ฅผ ์ดˆ๊ณผํ•˜๋ฉด DEAD_LETTER๋กœ ์ „ํ™˜๋ฉ๋‹ˆ๋‹ค.

Compensation

  • settlement ์‹คํŒจ:
    payment ์ทจ์†Œ ๋ณด์ƒ์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์ฃผ๋ฌธ์„ CANCELLED๋กœ ๋งˆ๋ฌด๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • notification ์‹คํŒจ:
    payment/settlement๋ฅผ ๋˜๋Œ๋ฆฌ์ง€ ์•Š๊ณ  notification policy์— ๋”ฐ๋ผ AUTO_RETRY, MANUAL_INTERVENTION, IGNORE๋กœ ๋ถ„๊ธฐํ•ฉ๋‹ˆ๋‹ค.

Notification Recovery

  • AUTO_RETRY
    notification event๋ฅผ RETRY_SCHEDULED๋กœ ๋‚จ๊ธฐ๊ณ , nextAttemptAt ์ดํ›„ due processor๊ฐ€ ์žฌ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • MANUAL_INTERVENTION
    ์šด์˜์ž ํ™•์ธ์ด ํ•„์š”ํ•˜๋ฉฐ notification event๋ฅผ MANUAL_INTERVENTION_REQUIRED๋กœ ๋‚จ๊น๋‹ˆ๋‹ค.
  • IGNORE
    ํ˜„์žฌ ๋ฒ”์œ„์—์„œ ์ฃผ๋ฌธ ์™„๋ฃŒ๋ฅผ ๋ง‰์ง€ ์•Š์•„๋„ ๋˜๋Š” ์‹คํŒจ๋กœ ๋ณด๊ณ  IGNORED ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

NotificationRetryProcessor๋Š” due retry ๋Œ€์ƒ๋งŒ ์กฐํšŒํ•˜๊ณ , ์ฒ˜๋ฆฌ ์ „ PROCESSING claim์„ ํš๋“ํ•œ ์ด๋ฒคํŠธ๋งŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

  • ์„ฑ๊ณต ์‹œ notification event๋ฅผ SENT๋กœ ์ „ํ™˜ํ•˜๊ณ  order๋ฅผ COMPLETED๋กœ ๋ณต๊ตฌํ•ฉ๋‹ˆ๋‹ค.
  • future retry event๋Š” ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • claim์— ์‹คํŒจํ•œ due event๋Š” ์ค‘๋ณต ์‹คํ–‰์œผ๋กœ ๋ณด๊ณ  skippedCount๋กœ ์ง‘๊ณ„ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฐ˜๋ณต ์‹คํŒจ ์‹œ backoff ์žฌ์Šค์ผ€์ค„ ๋˜๋Š” MANUAL_INTERVENTION_REQUIRED ์ „ํ™˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ์„ค์ •์—์„œ๋Š” notification.retry.scheduler.enabled=false๋กœ ๋น„ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
์†์„ฑ์„ ์ผœ๋ฉด property-gated NotificationRetryScheduler๊ฐ€ NotificationRetryProcessor๋ฅผ ์ฃผ๊ธฐ์ ์œผ๋กœ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
์šด์˜์ž๋Š” POST /api/admin/notification-events/retry-due๋กœ due notification retry batch๋ฅผ ์ˆ˜๋™ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‘๋‹ต์€ status, processedCount, successCount, failedCount, skippedCount, processedEventIds๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

Admin Reprocessing

  • POST /api/admin/notification-events/{id}/retry
    notification ์‹คํŒจ ๊ฑด์„ ์žฌ์ „์†ก ์„ฑ๊ณต์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ์ฃผ๋ฌธ์„ COMPLETED๋กœ ๋ณต๊ตฌํ•ฉ๋‹ˆ๋‹ค. ์‘๋‹ต์€ eventId, orderId, action=RETRY, result=SUCCESS, previousStatus, currentStatus, message๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
  • POST /api/admin/notification-events/{id}/ignore
    ๋ฌด์‹œ ๊ฐ€๋Šฅํ•œ notification ์‹คํŒจ ๊ฑด์„ IGNORED๋กœ ์ •๋ฆฌํ•˜๊ณ  ์ฃผ๋ฌธ์„ COMPLETED๋กœ ๋ณต๊ตฌํ•ฉ๋‹ˆ๋‹ค. ์‘๋‹ต์€ eventId, orderId, action=IGNORE, result=IGNORED, previousStatus, currentStatus, message๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
  • POST /api/admin/outbox-events/{id}/retry
    DEAD_LETTER outbox event๋งŒ ๋Œ€์ƒ์œผ๋กœ ์ฆ‰์‹œ ์žฌ๋ฐœํ–‰์„ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค. ์‘๋‹ต์€ eventId, aggregateId, eventType, action=RETRY_DEAD_LETTER, result, previousStatus, currentStatus, retryCount, failureCode, failureReason, message๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

์„ธ admin ์žฌ์ฒ˜๋ฆฌ API๋Š” ์„ ํƒ์  request body๋กœ operatorId, reason์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ์กด์ฒ˜๋Ÿผ body ์—†์ด ํ˜ธ์ถœํ•ด๋„ ๋™์ž‘ํ•˜๋ฉฐ, body๊ฐ€ ์—†๊ฑฐ๋‚˜ ๊ฐ’์ด ๋น„์–ด ์žˆ์œผ๋ฉด audit detail์—๋Š” operatorId=unknown, reason=not-provided๊ฐ€ ๊ธฐ๋ก๋ฉ๋‹ˆ๋‹ค. operatorId์™€ reason์€ trim/truncate ํ›„ audit detail์—๋งŒ ๋ฐ˜์˜ํ•˜๊ณ  metric tag๋‚˜ log field์—๋Š” ๋„ฃ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ admin ์žฌ์ฒ˜๋ฆฌ๋Š” ์ „์ฒด orchestration ์žฌ์‹คํ–‰์ด ์•„๋‹ˆ๋ผ, ์‹คํŒจํ•œ ํ•˜์œ„ ์ฒ˜๋ฆฌ ๋‹จ์œ„๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๋ณต๊ตฌํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.


8. ํ˜„์žฌ ๊ฒ€์ฆ ๋ฒ”์œ„

์ด ๋ ˆํฌ๋Š” "ํ๋ฆ„ ์ œ์–ด์™€ ์‹คํŒจ ์ฒ˜๋ฆฌ ๊ตฌ์กฐ๊ฐ€ ์‹ค์ œ๋กœ ๋™์ž‘ํ•˜๋Š”๊ฐ€"๋ฅผ ํ˜„์žฌ ๊ธฐ์ค€์œผ๋กœ ์•„๋ž˜๊นŒ์ง€ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.

  • ./gradlew compileJava
    ๋ฉ”์ธ ์†Œ์Šค ์ปดํŒŒ์ผ ํ™•์ธ
  • ./gradlew test
    H2 + MockMvc ์ค‘์‹ฌ ๋‹จ์œ„/ํ๋ฆ„ ๊ฒ€์ฆ
  • ./gradlew integrationTest
    PostgreSQL/Kafka Testcontainers ๊ธฐ๋ฐ˜ ํ†ตํ•ฉ ๊ฒ€์ฆ

ํ˜„์žฌ ์‹ค์ œ ๊ตฌํ˜„ ๋ฐ ๊ฒ€์ฆ ๋ฒ”์œ„๋Š” ์•„๋ž˜๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

  • order create / detail / flow API
  • JWT ๋ฐœ๊ธ‰ ๋ฐ /api/** ๋ณดํ˜ธ
  • orchestration happy path
  • settlement failure compensation
  • notification failure ๋ถ„๊ธฐ์™€ ignore policy
  • admin notification / outbox reprocessing
  • outbox publish ์ƒํƒœ ์ „์ด
  • PostgreSQL / Kafka ๊ธฐ๋ฐ˜ outbox happy path integration test
  • PostgreSQL / Kafka ๊ธฐ๋ฐ˜ outbox retry -> dead-letter integration test
  • notification AUTO_RETRY due processor
  • RETRY_SCHEDULED notification event ์žฌ์ฒ˜๋ฆฌ
  • retry ์„ฑ๊ณต ์‹œ notification SENT ๋ฐ order COMPLETED ๋ณต๊ตฌ
  • future retry event skip
  • ๋ฐ˜๋ณต ์‹คํŒจ ์‹œ retry backoff ๋˜๋Š” MANUAL_INTERVENTION_REQUIRED ์ „ํ™˜
  • Spring Modulith ApplicationModules.verify() ๊ธฐ๋ฐ˜ module boundary ๊ฒ€์ฆ

GitHub Actions workflow๋„ ์•„๋ž˜ ๋‘ job์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  • build-and-test
    compileJava, test, unit report upload
  • integration-test
    integrationTest, integration report upload

์ด๋ฒˆ ์ •๋ฆฌ ์‹œ์ ์˜ ๋กœ์ปฌ ์žฌ๊ฒ€์ฆ์—์„œ๋Š” test, integrationTest ๊ธฐ์ค€์„ ์„ ๋‹ค์‹œ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.
README์—์„œ๋Š” ๊ตฌํ˜„ ๋ฒ”์œ„๋ฅผ ๊ณผ์žฅํ•˜์ง€ ์•Š๊ณ , "๋ฌด์—‡์„ ๊ฒ€์ฆํ•˜๋Š” ๋ ˆํฌ์ธ์ง€"์™€ "์–ด๋””๊นŒ์ง€ ํ™•์ธํ–ˆ๋Š”์ง€"๋ฅผ ๋ถ„๋ฆฌํ•ด ์ ์Šต๋‹ˆ๋‹ค.


9. ๋ฌธ์„œ์™€ ๋‹ค์ด์–ด๊ทธ๋žจ ์œ„์น˜

ํ˜„์žฌ ์•„๋ž˜ draw.io ์ž์‚ฐ์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

  • overall architecture
  • overall architecture reference
  • order orchestration flow
  • outbox retry / dead-letter flow
  • notification retry / manual intervention flow
  • table relation overview

10. ์•„์ง ๋‚จ์€ ๋ฒ”์œ„

์•„๋ž˜๋Š” ํ˜„์žฌ๋„ ํ›„์† ๊ณผ์ œ๋กœ ์œ ์ง€ํ•˜๋Š” ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค.

  • ์‹ค์ œ payment provider๋ณ„ timeout / retry / error mapping ๊ณ ๋„ํ™”
  • WebClient timeout ์ดํ›„ provider confirmation flow ์„ค๊ณ„ ๋ฌธ์„œ: Payment Timeout Confirmation Flow ํ˜„์žฌ๋Š” mock/dummy provider ๊ธฐ๋ฐ˜ CONFIRMATION_REQUIRED ์ƒํƒœ ๊ธฐ๋ก๊นŒ์ง€๋งŒ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ external provider confirmation ์š”์ฒญ, admin confirmation API, OpenAPI path๋Š” Future Scope์ž…๋‹ˆ๋‹ค.
  • provider callback flow ๊ตฌํ˜„ ํŒ๋‹จ ๋ฌธ์„œ: Provider Callback Flow Review ํ˜„์žฌ๋Š” Future Scope / Design Review์ด๋ฉฐ production code, OpenAPI path, automated test๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • notification ์ฑ„๋„๋ณ„ retry policy ์„ธ๋ถ„ํ™”
  • dead-letter ์ด๋ฒคํŠธ์˜ ์šด์˜ ์ž๋™ํ™”
  • refresh token / key rotation / user store ์—ฐ๋™
  • admin ๋ ˆ๋ฒจ ์žฌ์ฒ˜๋ฆฌ / ์žฌ๊ฒ€์ฆ API ๊ณ ๋„ํ™”
  • provider callback API์™€ full WebClient timeout confirmation flow ๊ตฌํ˜„

์งง๊ฒŒ ๋งํ•ด ์ด ํ”„๋กœ์ ํŠธ๋Š” CRUD showcase๋ณด๋‹ค๋Š” ์ปค๋จธ์Šค ๊ฑฐ๋ž˜ ํ๋ฆ„์˜ orchestration, explicit state transition, failure handling, compensation, retry/dead-letter, ์šด์˜ ๋ณต๊ตฌ ์ง€์ ์„ ๋ณด์—ฌ์ฃผ๋Š” ํฌํŠธํด๋ฆฌ์˜ค ์„ฑ๊ฒฉ์ด ๊ฐ•ํ•ฉ๋‹ˆ๋‹ค.


11. Technical Discussion Points

์ด ํ”„๋กœ์ ํŠธ์˜ ์ฃผ์š” ์„ค๊ณ„ ์„ ํƒ์€ ์•„๋ž˜ ๊ด€์ ์—์„œ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒ์„ธ ์„ค๊ณ„ ๊ทผ๊ฑฐ, ๊ตฌํ˜„ ๊ทผ๊ฑฐ, ๊ฒ€์ฆ ๊ทผ๊ฑฐ, Boundary๋Š” Technical Discussion Points์™€ Technical Decisions์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1. ์™œ Orchestration ๊ตฌ์กฐ๋ฅผ ์„ ํƒํ–ˆ๋Š”๊ฐ€

์ฃผ๋ฌธ ์ดํ›„์—๋Š” payment, settlement, notification, outbox publish์ฒ˜๋Ÿผ
์„œ๋กœ ๋‹ค๋ฅธ ์‹คํŒจ ๊ฐ€๋Šฅ์„ฑ๊ณผ ๋ณต๊ตฌ ๊ธฐ์ค€์„ ๊ฐ€์ง„ ํ›„์† ํ๋ฆ„์ด ์ด์–ด์ง‘๋‹ˆ๋‹ค.

์ด ํ๋ฆ„์„ ๊ฐ service์— ํฉ๋ฟŒ๋ฆฌ๋ฉด
์–ด๋””๊นŒ์ง€ ์„ฑ๊ณตํ–ˆ๊ณ , ์–ด๋””์„œ ์‹คํŒจํ–ˆ์œผ๋ฉฐ, ์–ด๋–ค ๋‹จ์œ„๋กœ ๋ณต๊ตฌํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ CommerceOrchestrationService๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ์ „์ฒด ํ๋ฆ„์„ ์ฝํžˆ๊ฒŒ ๋งŒ๋“ค๊ณ ,
๊ฐ domain์€ ๊ณต๊ฐœ API ๊ณ„์•ฝ์„ ํ†ตํ•ด ํ˜‘๋ ฅํ•˜๋„๋ก ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

2. ์™œ ์‹คํŒจ๋ฅผ ํ•˜๋‚˜๋กœ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์•˜๋Š”๊ฐ€

payment ์‹คํŒจ, settlement ์‹คํŒจ, notification ์‹คํŒจ, outbox publish ์‹คํŒจ๋Š”
์ฃผ๋ฌธ ์ „์ฒด์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

payment ์‹คํŒจ๋Š” ์ฃผ๋ฌธ ์™„๋ฃŒ๋ฅผ ๋ง‰์•„์•ผ ํ•˜์ง€๋งŒ,
notification ์‹คํŒจ๋Š” ์ฃผ๋ฌธ ์ž์ฒด๋ฅผ ๋˜๋Œ๋ฆฌ๊ธฐ๋ณด๋‹ค retry, manual intervention, ignore ์ •์ฑ…์œผ๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ํŽธ์ด ๋” ์ž์—ฐ์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์‹คํŒจ๋ฅผ ๋‹จ์ˆœ exception์œผ๋กœ๋งŒ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๊ณ ,
์ƒํƒœ์™€ ์žฌ์ฒ˜๋ฆฌ ๊ธฐ์ค€์œผ๋กœ ๋‚จ๊ธฐ๋Š” ๊ตฌ์กฐ๋ฅผ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

3. ์ด ํ”„๋กœ์ ํŠธ๊ฐ€ ์ฆ๋ช…ํ•˜๋Š” Backend ์—ญ๋Ÿ‰

  • ์ƒํƒœ ์ „์ด ์ค‘์‹ฌ์˜ ๊ฑฐ๋ž˜ ํ๋ฆ„ ์„ค๊ณ„
  • ์‹คํŒจ ์ง€์ ๋ณ„ ๋ณด์ƒ / ์žฌ์‹œ๋„ / ์ˆ˜๋™ ๊ฐœ์ž… ๋ถ„๋ฆฌ
  • Outbox ๊ธฐ๋ฐ˜ ํ›„์† ์ด๋ฒคํŠธ ๋ฐœํ–‰ ๋ถ„๋ฆฌ
  • Spring Modulith ๊ธฐ๋ฐ˜ module boundary ๊ฒ€์ฆ
  • Testcontainers ๊ธฐ๋ฐ˜ PostgreSQL / Kafka integration test
  • ์šด์˜์ž๊ฐ€ ๋ณต๊ตฌํ•  ์ˆ˜ ์žˆ๋Š” admin reprocessing ํ๋ฆ„

12. ๋กœ์ปฌ ์‹คํ–‰

Prerequisites

  • Java 21
  • Docker

Quick Start

docker compose up -d
SPRING_PROFILES_ACTIVE=local ./gradlew bootRun

๊ธฐ๋ณธ ๋กœ์ปฌ ๊ฐ’์€ ์•„๋ž˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • PostgreSQL: jdbc:postgresql://localhost:5432/commerce_orchestration
  • Kafka: localhost:9092
  • Kafka UI: http://localhost:8085
  • payment provider mode: mock

.env.example์„ ์ฐธ๊ณ ํ•ด ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ๋งž์ถœ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

External Payment Provider ๊ณจ๊ฒฉ ํ™•์ธ

SPRING_PROFILES_ACTIVE=local \
PAYMENT_PROVIDER_MODE=external \
PAYMENT_PROVIDER_BASE_URL=http://localhost:8089 \
./gradlew bootRun

13. DB Schema / Migration

DB ์Šคํ‚ค๋งˆ๋Š” Flyway migration์„ ๊ธฐ์ค€์œผ๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ธฐ๋ณธ/๋กœ์ปฌ/ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ํ”„๋กœํ•„์€ Flyway๋ฅผ ์ ์šฉํ•œ ๋’ค JPA ddl-auto=validate๋กœ ๋งคํ•‘ ์ •ํ•ฉ์„ฑ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
๋‹จ์œ„ ํ…Œ์ŠคํŠธ์šฉ test ํ”„๋กœํ•„๋งŒ H2 create-drop๊ณผ flyway disabled๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

์šด์˜ ์ ๊ฒ€์šฉ SQL์€ docs/sql์— ์ •๋ฆฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.


14. Notification ์šด์˜ ์ •์ฑ…

  • AUTO_RETRY
    ์ผ์‹œ์  ์‹คํŒจ๋กœ ๊ฐ„์ฃผํ•˜๋ฉฐ notification event๋ฅผ RETRY_SCHEDULED๋กœ ๋‚จ๊น๋‹ˆ๋‹ค.
    due ์‹œ์ ์ด ๋œ ์ด๋ฒคํŠธ๋Š” NotificationRetryProcessor๋ฅผ ํ†ตํ•ด ์žฌ์ฒ˜๋ฆฌ๋˜๋ฉฐ, scheduler๋Š” ๊ธฐ๋ณธ ๋น„ํ™œ์„ฑ ์ƒํƒœ์—์„œ property๋กœ ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์šด์˜์ž๋Š” POST /api/admin/notification-events/retry-due๋กœ ๋™์ผ trigger๋ฅผ ์ˆ˜๋™ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ณ , batch ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ ์š”์•ฝ๊ณผ ์ฒ˜๋ฆฌ๋œ event id ๋ชฉ๋ก์„ ํ•จ๊ป˜ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • MANUAL_INTERVENTION
    ์šด์˜์ž ํ™•์ธ์ด ํ•„์š”ํ•˜๋ฉฐ notification event๋ฅผ MANUAL_INTERVENTION_REQUIRED๋กœ ๋‚จ๊น๋‹ˆ๋‹ค.
  • IGNORE
    ํ˜„์žฌ ๋ฒ”์œ„์—์„œ ์ฃผ๋ฌธ ์™„๋ฃŒ๋ฅผ ๋ง‰์ง€ ์•Š์•„๋„ ๋˜๋Š” ์‹คํŒจ๋กœ ๋ณด๊ณ  IGNORED ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ mock ๋ถ„๊ธฐ ๊ธฐ์ค€์€ ์•„๋ž˜ description ํ† ํฐ์œผ๋กœ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•ฉ๋‹ˆ๋‹ค.

  • FAIL_NOTIFICATION_RETRY
  • FAIL_NOTIFICATION_MANUAL
  • FAIL_NOTIFICATION_IGNORE
  • FAIL_NOTIFICATION

15. Blog / Notes


16. Docs

About

Spring Boot backend that orchestrates payment, settlement, notification, and outbox flows with explicit state transitions and recovery paths.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages