설계 단계에서 컨텍스트 맵, 테이블 명세서, 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 (결제 테이블)
| 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)
'Spring 개발일지' 카테고리의 다른 글
| [팀프로젝트] MSA 기반 티켓팅 프로그램 - 레이스 컨디션 발견 및 설계 재검토 (2) | 2026.04.23 |
|---|---|
| [팀프로젝트] MSA 기반 티켓팅 프로그램 - 결제 도메인 설계 2편 Kafka 기반으로 전면 수정 + 인프라 설계까지 (1) | 2026.04.22 |
| [팀프로젝트] MSA 기반 티켓팅 프로그램 - 결제 도메인 설계 및 API 구조 정리 (1) | 2026.04.20 |
| [팀프로젝트] MSA 기반 티켓팅 프로그램 - 결제 도메인 (1) | 2026.04.18 |
| [팀 프로젝트]MSA 기반 티켓팅 서비스 설계 및 도메인 분리 (프로젝트 기획 정리) (2) | 2026.04.17 |