결제 시스템(Payment System)은 사용자의 지불 요청을 받아 신용카드, 계좌이체, 간편결제 등 다양한 방식으로 거래를 처리하고 그에 대한 정산 및 회계 처리까지 포함하는 복합적인 시스템이다. 실시간으로 수많은 요청을 처리해야 하고 금전이 직접적으로 오가기 때문에 높은 정확성, 보안성, 확장성, 신뢰성이 필수적으로 요구된다.
구성 요소 | 설명 |
---|---|
Payment Gateway | 외부 결제 수단(카드사, PG사, 간편결제 등)과 연동하는 API |
Order / Payment API | 사용자의 결제 요청을 처리하는 진입점 |
결제 상태 관리 (State Machine) | 결제 요청 -> 승인 -> 정산 등 상태 전이 로직 관리 |
정산 시스템 (Settlement) | 거래 완료 후 가맹점에 수수료 계산 및 입금 처리 |
알림 시스템 | 결제 성공/실패, 환불, 수신 등을 사용자에게 전달 |
보안 모듈 | 암호화, 토큰화, 인증 등 민감 정보 보호 |
이벤트/로그 시스템 | 결제 흐름 추적 및 장애 분석용 이벤트 수집 |
결제는 금전이 오가는 작업이기 때문에 데이터 정합성이 가장 중요하다.
예를 들어 A가 결제했는데 계좌 차감은 되었지만 주문이 실패하면 안되기 때문이다.
결제 성공 후 처리해야 할 일은 많다.(정산, 포인트 적립, 알림, 영수증 발송 등).
모든 작업을 동기적으로 처리하면 느려지고 장애 발생 가능성도 커진다.
동일한 결제 요청이 두 번 처리되면 안 된다. (예: 사용자가 버튼을 두 번 누름)
사용자는 결제가 완료되었는지 여부를 명확히 알아야 하고 장애 상황에서도 재처리 가능해야 한다.
PENDING
, SUCCESS
, FAILED
)결제 정보는 법적으로도 민감정보(PII)에 해당하므로 암호화는 필수이다.
결제 결과에 따라 사용자나 가맹점에 즉시 알림을 줄 수 있어야 한다.
[Client] → [API Gateway] → [OrderService]
↘︎ Kafka (결제 이벤트 발행)
↘︎ PaymentProcessorService
↘︎ External PG API
↘︎ 결과 수신 → DB 상태 변경
↘︎ Kafka (후속 이벤트)
↘︎ 정산 / 알림 / 통계 처리
위 구조는 결제 요청부터 승인까지의 핵심 흐름을 나타낸다. Kafka 기반으로 이벤트를 나누어 처리하여 결제 로직과 후속 로직을 완전히 분리함으로써 확장성과 장애 대응력을 확보할 수 있다.
적용 기술 | 목적 | 효과 |
---|---|---|
Kafka 기반 이벤트 아키텍처 | 느린 연산 분리 | 빠른 응답 + 비동기 처리 |
Redis 락 / Lua | 중복 방지, 재고 제어 | 신뢰성 확보 |
SAGA 패턴 | 분산 트랜잭션 처리 | 보상 트랜잭션을 통한 상태 복구 가능 |
상태 머신 | 결제 상태 추적 | 장애 발생 시 재처리 용이 |
암호화 / 토큰화 | 보안 강화 | 법적 요건 충족, 사용자 신뢰 확보 |
알림 시스템 | 사용자 경험 개선 | 실시간 피드백 제공, 사용자 만족도 상승 |
이번에 결제 시스템의 전반적인 구조와 구성 요소, 그리고 그에 필요한 핵심 기술들을 정리하면서 단순히 "돈을 보내는 기능" 이상의 것들을 명확히 이해할 수 있었다. 결제 시스템은 단일 트랜잭션이 아닌 금전 흐름과 관련된 복합 이벤트를 신뢰성 있게 처리해야 하는 고난도의 분산 시스템이라는 점에서 일반적인 API 서비스와는 전혀 다른 설계 철학이 필요하다.
특히 크게 아래와 같은 부분을 깊이 이해하게 되었다.
결제는 단일 작업이 아닌 상태 전이 흐름(State Transition)으로 관리되어야 한다는 점
-> 결제 요청 -> 승인 -> 정산
과 같은 단계는 단순 DB 저장으로 끝나지 않으며 각각의 상태가 확실하게 관리되고 전이되어야 함을 깨달았다. 상태 머신이나 enum 기반 상태 관리 전략의 중요성을 알게 됐다.
강한 일관성과 성능을 동시에 만족시킬 수 없기 때문에, 상황에 맞는 트랜잭션 모델을 선택해야 한다는 점
-> 단일 DB 환경에서는 ACID를 마이크로서비스나 외부 PG 연동 환경에서는 SAGA 패턴이나 Event-driven 구조를 적용해야 함을 배웠고 이를 통해 분산 환경에서의 트랜잭션 설계 역량이 요구된다는 것을 느꼈다.
Kafka를 중심으로 한 비동기 이벤트 아키텍처가 필수적이라는 점
-> 결제 자체보다 이후의 정산, 알림, 적립 등의 후속 작업이 더 많기 때문에 처리 속도와 장애 대응력을 높이기 위해 결제 이후의 모든 흐름을 이벤트 기반으로 설계하는 것이 실무에서 가장 중요하다는 점을 이해했다.
Idempotency Key와 Redis 락을 활용한 중복 처리 방지의 중요성
-> 사용자가 같은 요청을 반복해서 보내더라도 시스템이 항상 같은 결과를 반환할 수 있도록 멱등성 보장(idempotency) 개념을 확실히 정립하게 되었다. 이를 구현하기 위해서는 Redis, Lua 스크립트, 분산락 등의 기술 조합을 상황에 맞게 사용할 수 있어야 한다는 것도 명확히 알게 됐다.
보안은 단순한 암호화의 문제가 아닌 전반적인 인프라와 설계 전반에 영향을 준다는 점
-> HTTPS, 토큰화, AES 암호화뿐 아니라 민감 정보의 저장 위치, 로그에 출력되지 않도록 하는 필터링 로직, 보안 규정(PIC-DSS)까지 실무에선 반드시 고려해야 하는 요소임을 인식하게 됐다.
이번 정리를 통해 결제 시스템을 구성할 때 단순한 기능 구현이 아닌 데이터 정합성, 확장성, 보안성, 복원력 등 다양한 관점에서 사고하고 설계해야 한다는 점을 깊이 있게 체감할 수 있었다. 앞으로는 이런 복잡한 트랜잭션 처리 시스템을 설계하거나 디버깅할 때 단순 로직 구현을 넘어서 “왜 이 구조를 선택해야 하는가”에 대한 기술적 근거를 명확히 제시할 수 있는 개발자가 되는 것이 목표다.