PayStream Kafka 토픽 & 이벤트 흐름
프로젝트 개요에서 그림 수준으로 정리한 MSA 구조를, Kafka 토픽·이벤트 계약·서비스 간 흐름까지 내려서 문서화한 글입니다.
동기 API(게이트웨이 REST)와 비동기 이벤트(Kafka)의 역할을 구분하고, 알림 서비스가 어떤 이벤트를 구독하는지까지 한곳에 모았습니다.
범위 안내
토픽 이름·페이로드는 팀 합의 기준의 설계안입니다. 일부는 백엔드 구현과 1:1로 맞춰 가는 중이며, 변경 시 이 문서를 함께 갱신합니다.
1. 전체 구조
1-1. 레이어 구분
flowchart TB
subgraph Client
WEB[PayStream-web<br/>Next.js]
end
subgraph Edge
GW[API Gateway :8000]
EU[Eureka]
CFG[Config Server]
end
subgraph Services
ORD[order-service]
INV[inventory-service]
PAY[payment-service]
NOTI[notification-service]
ADM[admin-service]
end
subgraph Messaging
KF[(Kafka)]
end
subgraph Data
R[(Redis)]
DB[(MySQL)]
end
WEB -->|REST + JWT| GW
GW --> ORD & INV & PAY & NOTI & ADM
ORD & INV & PAY & NOTI & ADM --> EU
ORD & INV & PAY & NOTI & ADM --> CFG
ORD & INV & PAY & NOTI --> KF
INV --> R
ORD & PAY & NOTI --> DB| 경로 | 용도 | 예시 |
|---|---|---|
| 동기 (REST) | 사용자 요청·즉시 응답이 필요한 작업 | 주문 생성, 결제 요청, 알림 목록 조회 |
| 비동기 (Kafka) | 다른 서비스 상태 변경 전파, 부하 분리 | 재고 차감, 결제 완료, 알림 발송 트리거 |
프론트는 게이트웨이 단일 URL만 호출합니다. (/api/notifications/... → notification-service /notifications/... — 연동 기록 참고)
1-2. 게이트웨이 라우팅 (알림 기준)
| 클라이언트 경로 | 게이트웨이 | 백엔드 서비스 |
|---|---|---|
GET /api/notifications/ping |
인증 예외 | notification-service /notifications/ping |
POST /api/notifications |
JWT 필수 | notification 생성 |
GET /api/notifications/email-templates |
JWT 필수 | 이메일 템플릿 (API 명세) |
2. Kafka 토픽 설계
2-1. 네이밍 규칙
paystream.{도메인}.{과거형_이벤트}- prefix
paystream.— 환경·클러스터 간 충돌 방지 - 도메인 —
order,inventory,payment,notification - 이벤트명 — 발생 이후 사실을 표현 (
created,completed,failed)
파티션 키는 가능한 한 비즈니스 ID(orderId, userId)를 사용해, 같은 주문에 대한 이벤트 순서를 보장합니다.
2-2. 토픽 목록 {#2-2-토픽-목록}
| 토픽 | Producer | Consumer | 설명 |
|---|---|---|---|
paystream.order.created |
order-service | inventory-service | 주문 생성 → 재고 선점 시도 |
paystream.inventory.reserved |
inventory-service | order-service, payment-service | 재고 확보 성공 → 결제 단계 진행 |
paystream.inventory.failed |
inventory-service | order-service, notification-service | 재고 부족 → 주문 실패·알림 |
paystream.payment.requested |
order-service | payment-service | PG 결제 요청 |
paystream.payment.completed |
payment-service | order-service, notification-service, inventory-service | 결제 성공 → 주문 확정·알림 |
paystream.payment.failed |
payment-service | order-service, notification-service | 결제 실패 → 주문 롤백·알림 |
paystream.order.cancelled |
order-service | inventory-service, notification-service | 사용자/시스템 취소 |
알림 서비스가 직접 구독하는 토픽 (담당 영역)
| 토픽 | 발송 채널 (예정) | 사용자 메시지 예 |
|---|---|---|
paystream.payment.completed |
EMAIL → PUSH | “결제가 완료되었습니다” |
paystream.payment.failed |
“결제에 실패했습니다” | |
paystream.inventory.failed |
“재고가 부족합니다” | |
paystream.order.cancelled |
“주문이 취소되었습니다” |
관리자 화면에서 POST /api/notifications로 수동 생성하는 경로는 Kafka와 별개로, 동기 API로 notification DB에 적재한 뒤 채널별 발송기를 태우는 구조입니다.
2-3. 토픽 설정 (권장값)
| 항목 | 권장 | 이유 |
|---|---|---|
| 파티션 수 | 3~6 (초기) | 서비스 인스턴스 수와 consumer group 균형 |
| retention | 7일 | 재처리·디버깅 여유 |
| replication | 3 (운영) | 브로커 장애 대비 |
| DLQ | paystream.{topic}.dlq |
처리 실패 메시지 격리 |
3. 핵심 시나리오: 예약·결제 Happy Path
숙소·특가 예약 주문이 성공할 때의 이벤트 순서입니다.
sequenceDiagram
actor U as 사용자
participant WEB as PayStream-web
participant GW as API Gateway
participant ORD as order-service
participant INV as inventory-service
participant PAY as payment-service
participant KF as Kafka
participant NOTI as notification-service
U->>WEB: 예약·결제 요청
WEB->>GW: POST /api/orders
GW->>ORD: 주문 생성
ORD->>ORD: DB 저장 (PENDING)
ORD->>KF: paystream.order.created
KF->>INV: consume
INV->>INV: Redis 재고 차감 + MySQL 반영
INV->>KF: paystream.inventory.reserved
KF->>ORD: consume
ORD->>KF: paystream.payment.requested
KF->>PAY: consume
PAY->>PAY: PG API 호출
PAY->>KF: paystream.payment.completed
KF->>ORD: consume (CONFIRMED)
KF->>NOTI: consume
NOTI->>NOTI: 채널 분기 (EMAIL / PUSH)
NOTI->>U: 알림 발송
WEB-->>U: 결제 완료 UI3-1. 실패 분기 (요약)
flowchart LR
OC[paystream.order.created] --> INV{재고}
INV -->|OK| IR[paystream.inventory.reserved]
INV -->|FAIL| IF[paystream.inventory.failed]
IF --> NOTI1[notification-service]
IR --> PR[paystream.payment.requested]
PR --> PG{PG}
PG -->|OK| PC[paystream.payment.completed]
PG -->|FAIL| PF[paystream.payment.failed]
PC --> NOTI2[notification-service]
PF --> NOTI3[notification-service]재고 실패·결제 실패 시 order-service는 주문 상태를 FAILED / CANCELLED로 바꾸고, 필요하면 paystream.order.cancelled를 추가 발행해 재고를 되돌립니다.
4. 이벤트 페이로드 (공통 envelope)
서비스마다 DTO가 달라도, Kafka 메시지 최상위는 공통 필드를 둡니다.
{
"eventId": "550e8400-e29b-41d4-a716-446655440000",
"eventType": "paystream.payment.completed",
"occurredAt": "2026-06-18T09:30:00Z",
"version": 1,
"payload": {
"orderId": "ord_20260618_001",
"userId": "user_42",
"amount": 89000,
"currency": "KRW",
"paymentId": "pay_abc123"
}
}| 필드 | 설명 |
|---|---|
eventId |
UUID, 멱등 처리 키 |
eventType |
토픽과 동일하거나 토픽 내 세부 타입 |
occurredAt |
이벤트 발생 시각 (ISO 8601) |
version |
스키마 버전 (breaking change 시 증가) |
payload |
도메인별 본문 |
notification-service는 payload.userId, payload.orderId를 기준으로 알림 API의 userId, channel, title, body를 조립합니다.
4-1. paystream.payment.completed payload 예
{
"orderId": "ord_20260618_001",
"userId": "user_42",
"paymentId": "pay_abc123",
"amount": 89000,
"currency": "KRW",
"productName": "제주 오션뷰 특가",
"paidAt": "2026-06-18T09:30:00Z"
}5. 알림 서비스 내부 흐름
Kafka 이벤트와 REST API 생성 요청이 같은 발송 파이프라인으로 합쳐지도록 설계합니다.
flowchart TB
subgraph Input
K[Kafka Consumer]
API[POST /api/notifications]
end
subgraph notification-service
MAP[이벤트 → NotificationCommand 매핑]
DB[(notifications DB)]
ROUTER{channel}
EMAIL[Email Sender]
PUSH[Web Push Sender]
end
K --> MAP
API --> MAP
MAP --> DB
DB --> ROUTER
ROUTER --> EMAIL
ROUTER --> PUSH| channel | 현재 | 다음 단계 |
|---|---|---|
EMAIL |
API 명세·템플릿 테이블 설계 완료 | 이벤트 기반 자동 발송 연결 |
PUSH |
설계만 | Web Push 로드맵 |
SMS |
미정 | — |
6. 설계 결정 기록 (ADR 요약)
Kafka를 쓰는 이유
- 주문·결제·재고·알림이 느슨하게 결합되어야 서비스별 배포·확장이 가능
- 피크 트래픽 시 알림 발송을 버퍼링해 PG·외부 API 지연을 흡수
- kickoff에서 비교한 RabbitMQ 대비 대용량 스트리밍·리플레이에 유리 (킥오프 글)
REST로 알림을 직접 호출하지 않는 이유 (도메인 이벤트 우선)
- order/payment 서비스가 notification API를 알면 동기 결합 + 장애 전파
- 이벤트 소비 실패 시 Kafka offset·DLQ로 재시도 정책을 통일할 수 있음
- 다만 관리자 테스트·수동 발송은 REST
POST /api/notifications유지
멱등성
eventId기준으로 notification-service DB에 처리 이력 저장- 동일
eventId재수신 시 발송 스킵
7. 구현 현황 (2026.06)
| 항목 | 상태 |
|---|---|
| API Gateway ↔ notification ping/POST | 완료 (worklog) |
| 이메일 템플릿·발송 API 명세 | 완료 (30-api) |
| Kafka 토픽 생성·ACL | 진행 중 |
| order → inventory → payment 이벤트 체인 | 설계 완료, 일부 구현 |
| notification Kafka Consumer | 설계 완료, EMAIL 연동 예정 |
| Web Push / VAPID | 미착수 |
8. 관련 글
| 글 | 관계 |
|---|---|
| 프로젝트 개요 | 상위 허브 |
| 킥오프 & 기술 스택 | 서비스별 스택 선정 근거 |
| 알림 API 명세 | REST·ERD 상세 |
| 알림 연동 우선순위 | 채널·프론트 로드맵 |
9. 변경 이력 {#9-변경-이력}
| 날짜 | 내용 |
|---|---|
| 2026-06-18 | 초안 작성 — 토픽 목록, Happy Path, envelope, 알림 파이프라인 |