Spring 개발일지

[팀프로젝트] MSA 기반 티켓팅 프로그램 - 결제 도메인 설계 및 산출물 도출

김둘리 2026. 4. 21. 09:59

설계 단계에서 컨텍스트 맵, 테이블 명세서, API 명세서, ERD, 시퀀스 다이어그램 총 5가지 산출물을 뽑아야 했는데 이걸 정리해보려고 한다. 실제 결제는 없이 토스페이먼츠 연동만 구현하는 방향으로 진행했다.


 전체 산출물 목록

  • 컨텍스트 맵 (Context Map)
  • 테이블 명세서
  • API 명세서
  • ERD
  • 시퀀스 다이어그램

1. 컨텍스트 맵 (Context Map)

컨텍스트 맵은 결제 도메인이 다른 도메인들과 어떻게 관계를 맺는지 보여주는 다이어그램이다.

결제 도메인의 주요 관계를 정리하면 이렇다.

연관 도메인관계 유형설명
예매(Booking) Customer/Supplier (Upstream) 예매 확정 시 결제 요청 트리거. Payment는 Booking의 Downstream
사용자(User) Shared Kernel / ACL user_id만 참조. 직접 의존 없음
Toss Payments Open Host Service (외부) REST API로 결제 승인·취소. ACL로 외부 모델 격리
알림(Notification) Downstream (이벤트) 결제 성공/실패 이벤트 발행 → 알림 도메인에서 소비

 

ACL(Anti-Corruption Layer)이란? 외부 시스템(토스페이먼츠)의 모델이 내부 도메인을 오염시키지 않도록 변환 레이어를 두는 패턴이다. 토스 API 응답 구조가 바뀌어도 내부 도메인 모델에는 영향이 없게 된다.

 


2. 테이블 명세서

P_PAYMENTS (결제 테이블)

컬럼명타입NULLKEYDEFAULT설명
id UUID NOT NULL PK   결제 ID
booking_id UUID NOT NULL FK   예매 ID
user_id UUID NOT NULL FK   사용자 ID
payment_key VARCHAR(200) NULL     토스 결제 키 (승인 후 저장)
order_id VARCHAR(64) NOT NULL UQ   주문 ID (토스 연동용, UUID 기반 생성)
final_amount BIGINT NOT NULL     최종 결제 금액 (원 단위)
status VARCHAR(20) NOT NULL   PENDING 결제 상태 (PENDING / SUCCESS / FAILED / REFUNDED)
requested_at TIMESTAMP NOT NULL     결제 요청 일시
approved_at TIMESTAMP NULL     결제 승인 일시
created_at TIMESTAMP NOT NULL     생성 일시
created_by UUID NOT NULL     생성자
updated_at TIMESTAMP NULL     수정 일시
updated_by UUID NULL     수정자
deleted_at TIMESTAMP NULL     삭제 일시 (소프트 딜리트)
deleted_by UUID NULL     삭제자

P_PAYMENTS_HISTORY (결제 이력 테이블)

컬럼명타입NULLKEYDEFAULT설명

id UUID NOT NULL PK   결제 기록 ID
payment_id UUID NOT NULL FK   결제 ID
status VARCHAR(20) NOT NULL   PENDING 변경된 결제 상태
reason VARCHAR(500) NULL     상태 변경 사유
toss_raw_response TEXT NULL     토스 원본 응답 JSON
created_at TIMESTAMP NOT NULL     생성 일시
created_by UUID NOT NULL     생성자
updated_at TIMESTAMP NULL     수정 일시
updated_by UUID NULL     수정자
deleted_at TIMESTAMP NULL     삭제 일시
deleted_by UUID NULL     삭제자

 

 

 

3. ERD

B_BOOKINGS ||--o| P_PAYMENTS : "1:0..1"
P_PAYMENTS ||--o{ P_PAYMENTS_HISTORY : "1:N"
U_USERS ||--o{ P_PAYMENTS : "1:N"
  • 예매 1건당 결제는 최대 1건
  • 결제 1건당 이력은 여러 건 (상태 변경될 때마다 쌓임)
  • 사용자 1명이 여러 결제를 가질 수 있음

4. API 명세서

5. 시퀀스 다이어그램

토스페이먼츠 결제 흐름을 4단계로 나눴다.

 

흐름 요약

1. Prepare — 서버에서 orderId 생성 후 PENDING 상태로 DB INSERT
2. 토스 결제창 — 클라이언트 SDK가 토스 결제창 띄움. 사용자가 카드 입력
3. Confirm— 토스에서 받은 paymentKey로 서버가 최종 승인 요청. 금액 검증 필수
4. 웹훅 — 토스가 비동기로 이벤트 전송. 멱등성 체크 후 이력 기록

---


설계하면서 제일 헷갈렸던 부분이 Prepare → Confirm 두 단계로 나뉘는 이유였는데
- Prepare 단계에서 DB에 먼저 기록을 남겨야 → 나중에 결제 실패/중단돼도 추적이 가능
- Confirm 단계에서 금액 재검증을 해야 → 프론트 변조 공격 방어
- 웹훅은 confirm과 별개로 이중 확인 용도 → 네트워크 문제로 confirm이 실패해도 복구 가능

토스 공식 문서에서도 이 흐름을 권장하고 있으니 참고하면 좋다.
다음 포스팅에서는 실제 Spring 코드 구현을 다뤄볼 예정이다.

참고
- [토스페이먼츠 개발자 센터](https://docs.tosspayments.com)