일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- prg 패턴
- 레디스 동시성
- AWS
- jwt 표준
- 프로그래머스
- docker
- 이분탐색
- spring event
- gRPC
- 구현
- branch 전략
- 알람 시스템
- piplining
- 백준
- 카카오
- 검색어 추천
- 좋은 코드 나쁜 코드
- 깊게 생각해보기
- 코드 계약
- 완전탐색
- BFS
- 숫자 블록
- 셀러리
- 객체지향패러다임
- 디버깅
- 쿠키
- 트랜잭샨
- 결제서비스
- 수신자 대상 다르게
- 누적합
- Today
- Total
코딩관계론
결제서비스 본문
규모 추정
하루에 100만 건의 트랜잭션을 처리해야 하는 상황입니다. 이를 초 단위로 나누면, 1초에 약 12건(TPS, Transactions Per Second)을 처리해야 하는 수준입니다. 이러한 요구사항을 고려할 때, 시스템 설계 시 성능보다는 안정성에 중점을 두는 것이 중요합니다.
시스템 선택 고려 사항
이 결제 시스템의 경우 성능적 요구사항이 상대적으로 낮기 때문에, 안정성을 최우선으로 고려해야 합니다. 이를 위해 동기식 통신보다는 비동기식 통신을 사용하는 것이 더 적합합니다. 그 이유는 다음과 같습니다:
- 장애 격리: 동기식 통신을 사용할 경우, 결제 서비스 제공사(PSP)에서 장애가 발생하면, 우리의 서버까지도 장애 영향을 받을 수 있어, 장애 격리가 어렵습니다.
- 확장성: 트래픽이 급격히 증가할 때, 동기식 통신 방식은 시스템 확장이 어렵습니다. 반면, 비동기식 통신은 이러한 상황에 더 유연하게 대응할 수 있습니다.
결제 흐름
- Checkout 과정 (1단계):
- 사용자는 Checkout Page에서 구매할 항목을 선택하고, 해당 정보를 서버에 전송합니다. 이때 서버는 구매 정보를 바탕으로 결제를 준비합니다.
- 결제 준비 및 토큰 생성 (2단계 ~ 4단계):
- Payment Service는 사용자의 결제 요청을 받아 결제를 위한 준비 작업을 수행합니다. 이 과정에서 nonce라는 고유한 일회용 토큰이 생성됩니다. 이 토큰은 이후 결제 과정에서 안전하게 거래를 처리하기 위해 사용됩니다.
- 생성된 결제 토큰은 다시 서버로 반환되며, 서버는 이 토큰을 통해 결제를 계속 진행할 수 있습니다. 반환된 토큰은 서버에 안전하게 저장됩니다.
- 결제 페이지로 리디렉션 (5단계):
- 사용자는 결제를 진행하기 위해 Hosted Payment Page로 리디렉션됩니다. 이 페이지는 결제 서비스 제공자(PSP)가 호스팅하는 페이지로, 사용자가 결제 정보를 입력하는 곳입니다. 이때 사용자는 신용카드 정보를 입력하거나 인증을 진행합니다.
- 결제 시작 및 인증 (6단계):
- Hosted Payment Page에서 사용자는 결제 정보를 입력하고, 결제가 시작됩니다. 이 과정에서 결제 서비스 제공자(PSP)는 사용자의 결제 정보를 인증합니다.
- 결과 처리 (7단계 ~ 8단계):
- 결제 서비스 제공자(PSP)는 결제 성공 또는 실패 여부를 판단하고, 그 결과를 Payment Service로 전송합니다. 이때 결제가 성공했으면 사용자는 Payment Completion Page로 리디렉션되고, 실패했으면 실패 페이지로 이동합니다.
- 결과 확인 및 후처리 (9단계):
- 결제 결과는 Payment Service에서 웹훅(webhook)을 통해 처리됩니다. 웹훅은 결제 완료 후 서버에 결과를 알리는 메커니즘입니다. 이를 통해 시스템은 결제 완료 상태를 기록하고, 필요한 후처리를 수행합니다.
쿠팡의 결제 흐름 추정
구매하기 버튼 클릭 (1단계)
- 사용자가 "구매하기" 버튼을 클릭하면, 쿠팡은 해당 URL을 호출하여 Checkout을 진행합니다. 쿠팡은 https://checkout.coupang.com/cart/checkout URL을 호출합니다
결제 준비 및 토큰 생성 (2단계 ~ 4단계)
- 이후 구매하기 버튼을 클릭하면, paymentToken, checkoutId, orderId와 같은 정보를 포함한 응답이 반환됩니다. 이러한 정보는 결제 준비 및 토큰 생성 과정에서 반환된 것입니다. 예시 URL: https://checkout.coupang.com/order
https://checkout.coupang.com/order
{
"success": true,
"resultTypeCode": "SUCCESS",
"data": {
"status": "GOOD",
"code": 0,
"object": {
"paymentToken": "8a24d9ce61ad41cf9309c61e0888133a",
"payServiceId": "COUPANG",
"orderId": 8100067101369,
"checkoutId": "1725209996060",
"payType": "ROCKET_CARD",
"successReturnUrl": "https://checkout.coupang.com/paymentResult?checkoutId=1725209996060&thankYouPageUrl=https%3A%2F%2Fmc.coupang.com%2Fdesktop%2Fthank-you%3ForderId%3D8100067101369%26price%3D34200%26retailPrice%3D34200%26payType%3DROCKET_CARD%26checkoutId%3D1725209996060%26hasCoupangGlobal%3Dfalse%26agentType%3DWEB%26isDirectOrder%3Dfalse%26checkoutType%3DDEFAULT",
"failReturnUrl": "https://checkout.coupang.com/paymentResult?checkoutId=1725209996060",
"checkoutUrl": "https://checkout.coupang.com/cart/checkout/1725209996060?paymentFailed=true",
}
}
}
결제 결과 처리 및 리디렉션 (7단계 ~ 8단계)
- 결제가 완료되면 사용자는 성공 또는 실패 URL로 리디렉션됩니다. 응답에서 확인할 수 있듯이, successReturnUrl, failReturnUrl, checkoutUrl과 같은 URL이 제공되며, 결제 완료 후 해당 URL로 사용자가 이동됩니다.
결제 실패 처리: 재시도 큐 및 실패 메시지 큐
결제 시스템에서 결제 실패는 다양한 이유로 발생할 수 있습니다. 네트워크 문제, PSP(결제 서비스 제공자)의 일시적인 장애, 사용자 인증 실패 등이 그 예입니다. 이러한 실패를 처리하기 위해 결제 시스템은 재시도 큐 및 실패 메시지 큐를 사용할 수 있습니다.
- 재시도 큐: 결제 시도가 실패했을 때, 해당 트랜잭션을 재시도 큐에 넣어 일정 시간 후 다시 시도하도록 합니다. 이 방법은 일시적인 문제로 인한 결제 실패를 극복하는 데 유용합니다.
- 실패 메시지 큐: 재시도 후에도 결제가 실패할 경우, 해당 트랜잭션은 실패 메시지 큐에 넣어 시스템 관리자나 관련 부서에서 후속 조치를 취할 수 있도록 합니다. 이 큐는 영구적인 장애나 기타 결제 실패 원인에 대한 분석을 위해 사용됩니다.
멱등성 보장: 정확히 한 번만 전달
멱등성(idempotency)은 결제 시스템에서 매우 중요한 개념입니다. 이는 동일한 요청을 여러 번 처리하더라도 시스템이 동일한 결과를 보장하도록 하는 것입니다. 멱등성을 보장하기 위해 다음과 같은 방법을 사용할 수 있습니다:
- Idempotency Key: 각 결제 요청에 대해 고유한 Idempotency Key를 생성하고, 서버는 이 키를 기반으로 동일한 요청이 반복되지 않도록 처리합니다. 이 키는 서버가 같은 트랜잭션을 여러 번 처리하지 않도록 보장합니다.
- 중복 방지 로직: 서버는 Idempotency Key를 활용해 이전에 처리된 결제 요청에 대해 동일한 결과를 반환하고, 새로운 처리를 하지 않도록 설정할 수 있습니다.
재시도 시나리오에서 발생할 수 있는 문제와 멱등성
재시도 시나리오에서 발생할 수 있는 주요 문제는 다음과 같습니다:
- 중복 결제: 네트워크 지연이나 서버 오류로 인해 사용자의 결제 요청이 여러 번 재시도될 수 있습니다. 이 경우 멱등성이 보장되지 않으면 동일한 결제가 여러 번 이루어질 수 있습니다. 이를 방지하기 위해 Idempotency Key를 사용하여 중복 처리를 방지해야 합니다.
- 타임아웃 문제: 결제 서비스 제공자가 일정 시간 내에 응답하지 않으면, 결제 요청이 타임아웃될 수 있습니다. 이때 사용자에게 결제 실패로 보여질 수 있지만, 실제로는 결제가 완료되었을 가능성이 있습니다. 이 상황에서도 멱등성을 보장하는 것이 중요합니다. 이를 통해 서버는 타임아웃 이후에 동일한 결제 요청이 들어와도 이미 처리된 트랜잭션이라는 것을 인식하고, 중복 결제를 방지할 수 있습니다.
멱등성 검사
결제 시스템에서 멱등성을 보장하기 위한 검사는 다음과 같이 이루어질 수 있습니다:
- 고유 키 체크: 결제 요청을 받을 때, 시스템은 요청에 포함된 Idempotency Key를 조회하고, 해당 키로 이미 처리된 요청이 있는지 확인합니다. 만약 처리된 요청이라면 새롭게 처리하지 않고, 기존 결과를 반환합니다.
- 트랜잭션 로그 관리: 모든 결제 요청과 응답을 트랜잭션 로그로 기록해, 동일한 요청이 들어올 때 이 로그를 참조해 중복 처리를 방지할 수 있습니다.
- 응답 캐싱: 이전에 처리된 결제 요청의 응답을 캐시하고, 동일한 요청이 재시도될 때 캐시된 응답을 반환하는 방식으로 중복 처리를 방지할 수 있습니다.
https://docs.tosspayments.com/guides/learn/payment-flow
https://newsletter.pragmaticengineer.com/p/designing-a-payment-system
'개발' 카테고리의 다른 글
레디스 동시성 개선 및 성능 향상 포인트 (0) | 2024.08.25 |
---|---|
TPS 2에서 TPS 10,000까지의 험난한 과정 (0) | 2024.08.22 |
Redis 객체가 소멸될 때 DB에 영속화하자 - 꿀팁있음 (0) | 2024.08.19 |
검색어 추천 서비스 V4(Sharding) (0) | 2024.08.13 |
CAP 이론 - Consistency (일관성), Availability (가용성), Partition Tolerance (파티션 감내) (0) | 2024.08.13 |