코딩관계론

결제서비스 본문

개발

결제서비스

개발자_티모 2024. 9. 2. 02:47
반응형

규모 추정

하루에 100만 건의 트랜잭션을 처리해야 하는 상황입니다. 이를 초 단위로 나누면, 1초에 약 12건(TPS, Transactions Per Second)을 처리해야 하는 수준입니다. 이러한 요구사항을 고려할 때, 시스템 설계 시 성능보다는 안정성에 중점을 두는 것이 중요합니다.

시스템 선택 고려 사항

이 결제 시스템의 경우 성능적 요구사항이 상대적으로 낮기 때문에, 안정성을 최우선으로 고려해야 합니다. 이를 위해 동기식 통신보다는 비동기식 통신을 사용하는 것이 더 적합합니다. 그 이유는 다음과 같습니다:

  1. 장애 격리: 동기식 통신을 사용할 경우, 결제 서비스 제공사(PSP)에서 장애가 발생하면, 우리의 서버까지도 장애 영향을 받을 수 있어, 장애 격리가 어렵습니다.
  2. 확장성: 트래픽이 급격히 증가할 때, 동기식 통신 방식은 시스템 확장이 어렵습니다. 반면, 비동기식 통신은 이러한 상황에 더 유연하게 대응할 수 있습니다.

결제 흐름

결제 흐름

 

  • 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단계)

결제 준비 및 토큰 생성 (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를 활용해 이전에 처리된 결제 요청에 대해 동일한 결과를 반환하고, 새로운 처리를 하지 않도록 설정할 수 있습니다.

재시도 시나리오에서 발생할 수 있는 문제와 멱등성

재시도 시나리오에서 발생할 수 있는 주요 문제는 다음과 같습니다:

  1. 중복 결제: 네트워크 지연이나 서버 오류로 인해 사용자의 결제 요청이 여러 번 재시도될 수 있습니다. 이 경우 멱등성이 보장되지 않으면 동일한 결제가 여러 번 이루어질 수 있습니다. 이를 방지하기 위해 Idempotency Key를 사용하여 중복 처리를 방지해야 합니다.
  2. 타임아웃 문제: 결제 서비스 제공자가 일정 시간 내에 응답하지 않으면, 결제 요청이 타임아웃될 수 있습니다. 이때 사용자에게 결제 실패로 보여질 수 있지만, 실제로는 결제가 완료되었을 가능성이 있습니다. 이 상황에서도 멱등성을 보장하는 것이 중요합니다. 이를 통해 서버는 타임아웃 이후에 동일한 결제 요청이 들어와도 이미 처리된 트랜잭션이라는 것을 인식하고, 중복 결제를 방지할 수 있습니다.

멱등성 검사

결제 시스템에서 멱등성을 보장하기 위한 검사는 다음과 같이 이루어질 수 있습니다:

  • 고유 키 체크: 결제 요청을 받을 때, 시스템은 요청에 포함된 Idempotency Key를 조회하고, 해당 키로 이미 처리된 요청이 있는지 확인합니다. 만약 처리된 요청이라면 새롭게 처리하지 않고, 기존 결과를 반환합니다.
  • 트랜잭션 로그 관리: 모든 결제 요청과 응답을 트랜잭션 로그로 기록해, 동일한 요청이 들어올 때 이 로그를 참조해 중복 처리를 방지할 수 있습니다.
  • 응답 캐싱: 이전에 처리된 결제 요청의 응답을 캐시하고, 동일한 요청이 재시도될 때 캐시된 응답을 반환하는 방식으로 중복 처리를 방지할 수 있습니다.

 

https://docs.tosspayments.com/guides/learn/payment-flow

 

결제 흐름 이해하기 | 토스페이먼츠 개발자센터

카드 결제 과정의 세 가지 핵심 단계인 요청, 인증, 승인을 이해할 수 있어요.

docs.tosspayments.com

https://newsletter.pragmaticengineer.com/p/designing-a-payment-system

 

Designing a Payment System

A full chapter from the newly released book System Design Interview: Volume 2.

newsletter.pragmaticengineer.com

 

반응형