SANGWOO.LOG
🔀
ssul
#paystream#kafka#msa#architecture#notification

PayStream Kafka 토픽 & 이벤트 흐름

2026.06.18

프로젝트 개요에서 그림 수준으로 정리한 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 EMAIL “결제에 실패했습니다”
paystream.inventory.failed EMAIL “재고가 부족합니다”
paystream.order.cancelled EMAIL “주문이 취소되었습니다”

관리자 화면에서 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: 결제 완료 UI

3-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를 기준으로 알림 APIuserId, 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, 알림 파이프라인

Kafka 토픽을 추가하거나 이름을 바꿀 때는 토픽 목록 표와 변경 이력을 함께 수정합니다.

👇 도움이 되셨다면 👇

© Powered by moowoo