Skip to content

Repository files navigation

TossPayment

이 프로젝트는 인프런의 견고한 결제 시스템 구축 강의를 보며 공부할 겸 만든 결제 시스템 프로젝트입니다.

Kotlin, Spring Boot, Kafka, PostgreSQL을 사용해 결제 생성부터 PSP 승인, 정산, 원장 기록, 복구까지 이어지는 전체 흐름을 헥사고날 아키텍처로 구현했습니다.

서비스 구성

서비스 포트 역할
payment-service 8081 체크아웃, PSP 승인, 아웃박스 릴레이, 복구 처리
wallet-service 8082 판매자 지갑 정산과 낙관적 락 기반 동시성 제어
ledger-service 8083 복식부기 원장 기록

아키텍처 원칙

모든 서비스는 헥사고날 아키텍처를 기준으로 구성했습니다.

  • domain: 프레임워크에 의존하지 않음
  • application: 포트와 도메인에만 의존
  • adapter.in: HTTP, Kafka, 스케줄러 같은 외부 입력 수신
  • adapter.out: DB, Kafka, Toss API 같은 외부 연동 구현
  • bootstrap: Spring 빈 설정과 wiring 담당

결제 흐름

클라이언트 → 체크아웃 → Toss 승인 요청 → Outbox 저장 → Kafka 발행
                                                        ↓
                              payment.confirmed → wallet-service → wallet.updated ─┐
                                              └→ ledger-service → ledger.updated ──┤
                                                                                   ↓
                                                         payment-service가 최종 완료 처리

신뢰성 설계

항목 적용 위치
Transactional Outbox payment-service: 승인 성공 후 바로 Kafka에 보내지 않고 outbox에 저장한 뒤 relay
멱등 소비 wallet-service, ledger-service: processed-message 테이블로 중복 메시지 방지
낙관적 락 wallet-service, payment-service: @Version과 재시도로 동시성 충돌 완화
Dead Letter Queue 세 서비스 모두 비재시도 가능 실패를 .dlt 토픽으로 이동
Recovery Scheduler payment-service: EXECUTING, UNKNOWN 상태를 주기적으로 스캔

로컬 실행

필수 준비물:

  • Java 17
  • Docker

인프라 실행:

docker compose -f infra/docker-compose.yml up -d

애플리케이션 실행:

docker compose -f infra/docker-compose.yml up --build payment-service wallet-service ledger-service

로컬 엔드포인트

항목 URL
PostgreSQL localhost:5432
Kafka localhost:9092
Kafka UI http://localhost:8080
Payment 헬스체크 http://localhost:8081/actuator/health
Wallet 헬스체크 http://localhost:8082/actuator/health
Ledger 헬스체크 http://localhost:8083/actuator/health

주요 Payment API

메서드 경로 설명
POST /api/checkout 결제 주문 생성
GET /api/payments/{orderId} 결제 상태와 주문별 wallet/ledger 진행 상황 조회
POST /api/payments/recovery/scan 수동 복구 스캔 실행
GET /api/payments/recovery/pending 복구 대상 결제 목록 조회
GET /payments/success 결제 성공 리다이렉트 페이지

설정

Toss 시크릿 키는 TOSS_SECRET_KEY 환경 변수로 주입합니다. PSP 호출 타임아웃은 기본적으로 connect 3초, read 10초입니다.

payment:
  toss:
    connect-timeout: 3s
    read-timeout: 10s

Kafka consumer 재시도 설정은 서비스별로 조정할 수 있습니다.

<service>:
  messaging:
    retry-attempts: 2
    retry-backoff: 1s
    retry-max-backoff: 10s
    retry-multiplier: 2.0
    retry-jitter: 0.2
    dead-letter-suffix: .dlt

현재 한계

  • PSP 정산 파일 기반 reconciliation은 아직 구현하지 않았습니다.
  • 운영용 대시보드나 관리자 UI는 최소 수준만 구현되어 있습니다.

빌드 메모

  • Java 17 환경이 필요합니다.
  • Gradle 9에서 Kotlin/Detekt 플러그인 관련 deprecation warning이 일부 남아 있지만 테스트는 통과합니다.

About

토스페이먼츠 결제 승인부터 정산, 원장 기록, 복구까지 다루는 헥사고날 아키텍처 기반 결제 시스템 프로젝트

Topics

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages