결제 라우팅 A/B 테스트 체크리스트 2026: 승인율·비용·차지백 비교
결제 라우팅 A/B 테스트 체크리스트 2026: 승인율·비용·차지백 비교
결제 processor를 하나 더 연결한 뒤 “승인율이 더 높은 경로로 보내자”고 결정하기는 쉽습니다. 어려운 부분은 두 경로에 정말 비교 가능한 거래가 들어갔는지, 승인 뒤 capture와 환불까지 같은 기준으로 집계했는지, processor 수수료와 환전·분쟁 비용을 빠뜨리지 않았는지 증명하는 일입니다.
결제 라우팅 A/B 테스트는 화면 문구를 바꾸는 일반적인 웹 실험과도 다릅니다. 결제 결과는 즉시 성공 또는 실패로만 끝나지 않습니다. 처음에는 승인됐지만 capture되지 않을 수 있고, 환불·수수료 조정·dispute가 며칠 또는 그보다 늦게 도착할 수 있습니다. processor가 돌려주는 decline code와 상태 이름도 서로 다를 수 있습니다.
따라서 이 글에서는 제품 추천보다 실험 단위, cohort, metric dictionary, 승인·capture·순매출 분리, 비용, 지연 dispute, 중단·rollback, 결과표에 집중합니다. 여러 제품의 routing·vault 범위를 먼저 고르는 단계라면 결제 오케스트레이션 플랫폼 비교 2026을 확인하세요. 장애가 발생하기 전에 대체 경로 자체를 준비하는 일은 결제 공급사 failover·multi-gateway 준비 체크리스트의 범위입니다.
기능과 공식 문서는 2026년 8월 1일 확인 기준입니다. 계정·국가·통화·결제수단·merchant account·계약에 따라 지원 범위와 비용이 달라질 수 있으므로 실제 계정 화면과 계약서를 함께 확인해야 합니다. 이 글은 결제 운영을 위한 일반 체크리스트이며 법률·세무·회계 또는 PCI DSS 준수 조언이 아닙니다. 특정 설계를 적용해도 승인율 상승, 비용 절감, 분쟁 감소 또는 규정 준수가 보장되지 않습니다.
먼저 결론: 라우팅 승자는 승인율 한 줄로 정하지 않습니다
실험을 시작하기 전에 다음 순서를 문서로 고정합니다.
[비교 가능한 거래군과 제외군 정의]
↓
[고객 단위의 안정적인 A/B 배정]
↓
[공통 상태·비용 metric dictionary 확정]
↓
[소규모 관찰 → 확대 또는 중단]
↓
[capture·refund·fee·dispute 성숙 대기]
↓
[순매출 결과표·예외·결측을 함께 승인]
↓
[채택, 추가 실험 또는 원래 경로 rollback]
최종 판단에는 최소한 다음 질문이 함께 들어가야 합니다.
| 판단 질문 | 단독으로 보면 생기는 오류 | 함께 볼 자료 |
|---|---|---|
| authorization은 얼마나 성공했는가 | 승인 후 capture 실패·취소를 성공으로 셀 수 있음 | auth 상태, capture 상태, 최종 payment 상태 |
| 고객이 실제로 결제를 완료했는가 | 중복 시도와 checkout 재진입을 여러 건으로 셀 수 있음 | customer·order·invoice·attempt ID |
| 비용을 제한 뒤 남은 금액은 무엇인가 | processor fee, 환전, refund, dispute 조정을 놓칠 수 있음 | balance transaction, fee report, payout·대사 자료 |
| 나중에 불리해진 거래는 없는가 | 아직 접수되지 않은 dispute를 0으로 확정할 수 있음 | cohort별 관찰 종료일, dispute 발생·결과 상태 |
| 운영상 되돌릴 수 있는가 | 결과가 좋아 보여도 webhook·대사·지원 부하가 감당되지 않을 수 있음 | rollback runbook, queue, reconciliation exception |
“B 경로의 승인율이 높았다”는 중간 관찰일 뿐입니다. 결과표에는 분모, 제외 이유, 결측, 관찰 창과 비용 포함 범위를 같이 적어야 다른 팀이 같은 결론을 재현할 수 있습니다.
1. 기존 글과 검색 의도를 먼저 분리합니다
결제 관련 프로젝트는 서로 연결되지만 산출물이 다릅니다. 이번 실험 문서가 기존 비교·이전·장애 문서와 섞이지 않도록 역할을 다음처럼 나눕니다.
| 문서 | 중심 질문 | 이번 글에서 다루지 않는 범위 |
|---|---|---|
| 결제 오케스트레이션 플랫폼 비교 | Primer·Spreedly·Recurly 중 어떤 제품 범위를 검토할 것인가 | 제품 shortlist와 구매 평가 |
| failover·multi-gateway 준비 체크리스트 | 한 경로가 중단됐을 때 안전하게 전환할 기반이 있는가 | 장애 전 아키텍처 준비 |
| 결제 토큰 이전 체크리스트 | 기존 결제수단을 새 vault·processor에서 재사용할 수 있는가 | token export·import와 고객 ID mapping |
| 이 글 | 정상 운영 중 비교 가능한 거래를 두 경로에 배정해 어떤 결과가 나왔는가 | 제품 구매, 전체 token 이전, 장애 복구 자체 |
실험 전에 두 경로가 모두 정상적으로 결제를 생성·조회·취소·환불할 수 있어야 합니다. 아직 한 경로의 token 사용 가능 여부나 webhook 정합성이 불확실하다면 A/B 테스트가 아니라 준비 작업부터 끝냅니다. 장애 복구 중 트래픽을 임의 배정해 얻은 데이터도 정상 조건의 라우팅 실험과 섞지 않습니다.
2. 가설을 하나의 의사결정 문장으로 씁니다
가설은 “processor B가 더 좋을 것이다”가 아니라 다음 형식으로 작성합니다.
> 동일한 자격 조건을 충족한 거래를 사전 정의한 방식으로 A와 B에 배정했을 때, B가 guardrail을 위반하지 않으면서 최종 capture 또는 순매출 기준에서 운영상 채택 가능한 차이를 보이는지 검증한다.
가설 문서에는 아래 항목을 채웁니다.
- 대상 거래군: 국가, 통화, 결제수단, recurring·one-time, 신규·기존 고객, merchant account 범위
- 실험 단위: customer, subscription, invoice, order 중 무엇으로 고정할지
- 대조군 A: 현재 기본 processor와 routing 규칙 버전
- 실험군 B: 비교 processor와 routing 규칙 버전
- 주요 metric: authorization, capture, net revenue 중 의사결정에 가장 가까운 하나
- guardrail: duplicate, processing error, checkout latency, refund·dispute, reconciliation exception, 고객 문의
- 관찰 창: 즉시 결과를 보는 구간과 지연 결과를 성숙시키는 구간
- 결정권자: 시작, 확대, 중단, 최종 채택을 승인하는 담당자
- rollback 대상: 어떤 flag·workflow·routing version을 원래 값으로 되돌리는지
Primer의 결제 A/B 테스트 안내는 결제 실험을 구성할 때 확인할 공식 출발점입니다. Primer Workflows를 사용하는 경우에도 단순히 workflow를 복제하는 데서 끝내지 말고, 각 거래에 experiment_id, variant, routing_version, assigned_at을 남겨야 합니다. 플랫폼 기능 이름과 관계없이 누가 언제 어떤 규칙으로 배정했는지가 재현돼야 합니다.
3. 비교 가능한 cohort를 만들고 거래 중간 이동을 막습니다
cohort는 결제가 시작되기 전에 정합니다
결과를 본 뒤 국가·통화·카드 유형을 골라내면 유리한 구간만 남길 수 있습니다. 실험 시작 전에 포함·제외 기준을 문서화하고 변경 시 새 버전을 부여합니다.
| cohort 항목 | 포함 예시 | 제외 또는 별도 실험 예시 |
|---|---|---|
| 지역·통화 | 두 processor가 같은 결제수단과 통화를 정상 지원 | 한쪽만 지원하거나 별도 merchant account를 쓰는 지역 |
| 고객 상태 | 실험 시작 뒤 생성된 신규 고객 | 기존 token이 한 processor에만 묶인 고객 |
| 결제 유형 | one-time 카드 결제 | subscription renewal, 계좌이체, wallet을 한 표에 혼합 |
| 인증 조건 | 양쪽에서 동일하게 처리 가능한 인증 흐름 | 한쪽만 별도 고객 동작이 필요한 거래 |
| 주문 상태 | 동일한 checkout·가격·재고 정책 | 수동 invoice, 상담원이 만든 예외 주문 |
| 운영 사건 | 정상 운영 시간의 거래 | provider 장애·대규모 내부 incident 구간 |
| 데이터 품질 | order와 payment ID 연결이 완전한 거래 | assignment 또는 최종 상태가 없는 레코드 |
제외된 거래를 삭제하지 말고 excluded_reason을 남깁니다. 제외율 자체가 한 경로의 통합 범위가 좁거나 데이터 연결이 깨졌다는 신호일 수 있습니다.
배정은 가능한 한 안정적으로 유지합니다
한 고객이 첫 시도는 A, 다음 시도는 B로 계속 이동하면 고객 특성과 재시도 효과가 섞입니다. 고객 또는 subscription처럼 실험 기간 동안 유지할 수 있는 키를 정하고 같은 키는 같은 variant로 보내는 방식을 우선 검토합니다. 단, 어떤 키가 적합한지는 결제 모델과 개인정보 처리 기준에 맞게 정해야 합니다.
random() 호출 결과만 애플리케이션 로그에 남기는 방식보다 다음 필드를 별도 실험 테이블에 저장하는 편이 추적에 유리합니다.
experiment_id
assignment_key_hash
variant
cohort_version
routing_version
assigned_at
eligibility_result
excluded_reason
order_id / invoice_id
payment_attempt_id
processor_payment_id
원본 고객 식별정보나 민감 결제정보를 분석용 표에 무분별하게 복사하지 않습니다. 분석자가 필요한 것은 재현 가능한 연결키와 상태이지 카드 원문 데이터가 아닙니다.
retry와 failover를 A/B 배정으로 위장하지 않습니다
최초 시도가 A에서 실패하고 B로 넘어간 거래는 “B의 독립 표본”이 아닙니다. 이미 한 번 실패한 조건을 가진 거래이므로 처음부터 B에 배정된 거래와 분리해야 합니다. 다음 세 유형을 별도 필드로 저장합니다.
primary_A: 처음부터 A에 배정된 거래primary_B: 처음부터 B에 배정된 거래fallback_after_failure: 최초 경로 실패 뒤 제한된 정책으로 이동한 거래
fallback 정책은 실험 결과를 좋게 만들기 위한 공격적 재시도 규칙이 아닙니다. 고객에게 중복 청구 위험을 만들지 않도록 공급사 원문 상태, 멱등 처리, 최대 실행 범위와 중단 조건을 먼저 검토합니다. 장애 전환 설계는 앞서 소개한 multi-gateway 준비 체크리스트에서 별도로 확인하세요.
4. metric dictionary를 코드보다 먼저 확정합니다
processor마다 succeeded, authorized, captured, paid가 가리키는 범위가 다를 수 있습니다. dashboard 숫자를 그대로 합치지 말고 내부 공통 상태와 원본 상태를 함께 저장합니다.
공통 event 사전
| 공통 event | 운영 정의 | 필요한 원본 증거 | 섞으면 안 되는 상태 |
|---|---|---|---|
| eligible_attempt | cohort 조건을 충족하고 variant가 배정된 결제 시도 | assignment, order·invoice, created time | 실험 제외·사전 검증 실패 |
| submitted | processor에 결제 요청이 접수됨 | request ID, processor payment ID | client 단계 이탈 |
| authorized | processor 원문에서 승인이 확인됨 | 원문 상태, amount, currency, timestamp | 요청 접수·처리 중 |
| captured | 의도한 금액의 capture가 최종 확인됨 | capture ID, captured amount | authorization만 존재 |
| settled_or_reconciled | balance·payout 자료와 연결됨 | balance transaction, payout 또는 대사 ID | dashboard 성공 표시만 존재 |
| refunded | 전액·부분 환불이 확인됨 | refund ID, amount, status | void·미capture 취소 |
| disputed | dispute가 접수됨 | dispute ID, amount, reason, created time | 고객 문의만 존재 |
| duplicate_suspected | 같은 business action이 둘 이상 실행됐을 가능성 | idempotency key, order·invoice, payment IDs | 고객의 정상적인 별도 구매 |
Stripe Payment Intents 공식 문서는 결제 흐름이 여러 상태를 거칠 수 있음을 확인할 자료입니다. Stripe의 상태를 공통 모델의 정답으로 그대로 쓰라는 뜻은 아닙니다. A와 B의 원문 상태를 보존한 뒤 내부 공통 event로 변환하고, 변환 규칙에도 버전을 붙입니다.
분모를 metric 이름에 포함합니다
“승인율”이라는 이름만 두면 팀마다 다른 분모를 사용할 수 있습니다. 다음처럼 수식과 제외 규칙을 함께 적습니다.
authorization_rate = authorized attempts / submitted eligible attempts
capture_rate = captured eligible payments / authorized eligible payments
end_to_end_capture_rate = captured eligible payments / submitted eligible attempts
customer_completion_rate = completed unique orders / assigned eligible orders
이 수식은 보편적인 회계 기준이 아니라 실험을 재현하기 위한 운영 정의 예시입니다. 실제 조직에서는 부분 capture, 복수 통화, 여러 payment attempt가 붙은 주문을 어떻게 셀지 별도로 합의해야 합니다. 비율 옆에는 반드시 분자와 분모의 실제 건수를 표시합니다.
authorization은 빠르게 볼 수 있지만 최종 매출이 아닙니다. 비교할 때는 processor가 제공한 decline 원문과 내부 정규화 reason을 함께 둡니다. Stripe decline code 문서는 Stripe 경로의 실패 이유를 해석할 공식 자료지만, 다른 processor의 code를 Stripe code로 억지 변환하면 안 됩니다.
| 저장 필드 | 이유 |
|---|---|
| processor_decline_code | 공급사 원문으로 재검증하기 위해 보존 |
| normalized_decline_family | insufficient funds, authentication, suspected fraud, processing error 등 내부 분석 그룹 |
| customer_action_required | 고객이 추가 동작을 완료해야 하는지 분리 |
| retryable_by_policy | 기술적으로 가능하다는 뜻이 아니라 회사 정책상 후속 action 허용 여부 |
| final_status_checked_at | timeout·처리 중 응답을 실패로 조기 확정하지 않기 위해 필요 |
decline 이유는 고객을 평가하거나 우회 전략을 공격적으로 만드는 데 사용하지 않습니다. 카드 발급사의 판단을 회피하려고 반복 제출하는 방법도 권하지 않습니다. 운영팀은 공식 상태와 고객 안내, 제한된 후속 처리 정책을 기준으로 대응해야 합니다.
hard decline·3DS·timeout·5xx는 같은 실패로 묶지 않습니다
재시도 횟수가 늘면 승인율이 좋아 보일 수 있지만, 서로 다른 결과를 한 실패군으로 합치거나 같은 주문을 양쪽 processor에 동시에 보내면 실험이 아니라 중복 결제 위험이 됩니다. Stripe 오류 처리 문서와 3D Secure 문서는 Stripe 경로의 상태·후속 동작을 확인할 자료입니다. 다른 processor에서는 그 공급사의 원문 상태와 재시도 지침을 기준으로 별도 mapping을 만듭니다.
| 원문 결과 유형 | 실험상 분류 | 안전한 후속 처리 원칙 |
|---|---|---|
| hard decline | 발급사·processor가 명시한 비재시도 decline | 승인율을 높이려고 자동으로 다른 경로에 반복 제출하지 않고, 공식 안내에 따라 고객의 결제수단 변경 등 필요한 동작을 요청 |
| 3DS·추가 인증 필요 | 실패가 아니라 customer_action_required |
동일한 인증 조건과 완료 창을 적용하고, 고객 완료·이탈·만료를 별도 상태로 집계 |
| timeout·연결 중단 | 결과 미확정 | 새 결제를 만들기 전에 원래 processor 상태와 webhook을 조회하고, order·invoice와 idempotency 연결로 기존 action 존재 여부 확인 |
| HTTP 5xx·일시적 processing error | 결과 미확정 또는 정책상 제한 재시도 | 공급사 문서가 허용한 범위·간격·최대 횟수 안에서만 처리하고, 응답 없음 자체를 최종 실패로 단정하지 않음 |
| soft decline·재시도 가능 상태 | 정책상 후속 action 후보 | 원문 code, 이전 attempt, 고객 동작 필요 여부를 확인하고 사전 승인한 retry policy 적용 |
idempotency key가 한 processor 안에서 중복 요청을 막아준다고 해도 다른 processor에 새 action을 만드는 것까지 자동으로 막아준다고 가정해서는 안 됩니다. 교차 processor 재시도 전에는 원래 action의 최종 상태, 동일 order·invoice의 기존 payment ID, capture 가능 상태를 확인합니다. 재시도 건은 최초 배정 표본과 분리하고 retry_reason, retry_count, previous_processor_payment_id, idempotency_scope를 남깁니다.
2층: capture와 주문 완료
승인과 capture가 분리된 결제에서는 승인 건수만 비교하면 안 됩니다. 부분 capture, authorization 취소, capture 지연, 주문 취소를 따로 집계합니다. 주문 한 건에 payment attempt가 여러 개 붙을 수 있으므로 attempt 단위 표와 order 단위 표를 동시에 만듭니다.
attempt table: 요청·승인·실패 이유와 processor 성능 확인
order table: 고객이 실제로 한 번의 구매를 완료했는지 확인
financial table: capture·refund·fee·dispute·payout 연결 확인
3층: 순매출 관찰값
실험용 순매출은 회사의 회계상 매출 인식과 같은 뜻으로 쓰지 않습니다. 이번 실험에서 비교하려는 현금성 결과의 구성요소를 명시한 운영 관찰값으로 이름을 제한합니다.
observed_net_amount
= captured amount
- refunded amount
- processor fee included in scope
- dispute debit included in scope
- other explicitly named adjustments
어떤 수수료와 조정을 포함했는지 cost_scope_version으로 남깁니다. 세금, 회계상 수익, 환율 손익 또는 미래 dispute를 임의로 추정해 한 숫자로 확정하지 않습니다. 월말 자료와 payout을 맞추는 과정은 구독 청구 월말 대사 체크리스트를 함께 적용하세요.
6. 비용은 공개 가격표가 아니라 실제 거래 원본으로 비교합니다
processor 비용을 비교할 때 계약상의 명목 요율만 적용하면 실제 거래의 국가·통화·결제수단·환전·분쟁 조정을 놓칠 수 있습니다. 반대로 payout 입금액만 보면 여러 날짜와 거래가 묶여 어떤 variant의 비용인지 구분하기 어렵습니다.
다음 cost ledger를 payment ID에 연결합니다.
| 비용·조정 항목 | 연결키 | 집계 시 주의할 점 |
|---|---|---|
| 기본 처리 수수료 | processor payment 또는 balance transaction ID | 계약·통화·결제수단별 차이를 실제 원본으로 확인 |
| 국제·환전 등 추가 조정 | balance 또는 fee line ID | 적용 여부와 환율 시점을 별도 필드로 보존 |
| refund 관련 조정 | refund와 원결제 ID | 환불액과 환불 처리 관련 비용을 구분 |
| dispute 관련 debit·credit | dispute와 원결제 ID | 접수 시점과 최종 결과 시점이 다를 수 있음 |
| payout 조정 | payout·balance transaction ID | 거래별 귀속이 가능한 항목과 불가능한 항목 구분 |
| 오케스트레이션 비용 | 계약 또는 사용량 export | processor 비용과 중복 계산하지 않도록 범위 명시 |
Stripe Reports 문서와 Stripe Balance report는 Stripe 경로의 보고서 범위를 확인할 공식 자료입니다. Stripe payout reconciliation 문서는 payout과 개별 balance transaction을 연결할 때 참고할 수 있습니다. 다른 processor는 해당 공급사의 동일 성격 원본을 사용하고, 서로 다른 보고서의 날짜 기준을 먼저 맞춥니다.
복수 통화를 하나의 기준 통화로 보여줘야 한다면 원거래 통화·금액, 변환 통화·금액, 적용한 환율 출처와 시점을 모두 보존합니다. 환율 선택은 조직의 재무 정책에 따라 별도로 승인하고, 이 글의 실험 수식으로 회계 처리를 확정하지 않습니다.
7. dispute·차지백은 지연 지표로 운영합니다
실험 종료일에 dispute가 0건이라고 해서 해당 cohort의 분쟁 결과가 확정된 것은 아닙니다. 결제와 dispute 사이에 시차가 있으므로 “현재까지 관찰된 값”과 “관찰을 닫을 수 있는 cohort”를 분리합니다.
Stripe 분쟁 문서는 Stripe 경로에서 dispute lifecycle과 상태를 확인할 공식 출처입니다. 실제 허용 자료, 제출 기한과 결과는 사용 중인 processor의 현재 화면을 기준으로 확인해야 합니다. 분쟁 대응 절차와 증빙 운영은 B2B SaaS 결제 분쟁·차지백 운영 체크리스트로 분리하세요.
dispute 성숙 상태를 따로 표시합니다
| cohort 상태 | 의미 | 허용되는 표현 |
|---|---|---|
| open | 관찰 창이 아직 끝나지 않음 | 현재까지 접수된 dispute 수와 금액 |
| maturing | 신규 라우팅은 끝났지만 지연 결과를 기다림 | 잠정 결과, 최종 비교 금지 |
| closed_by_policy | 사전 정의한 관찰 창과 데이터 점검 완료 | 해당 정책 범위의 확정 결과 |
| reopened | 늦은 조정·누락이 발견돼 재검토 | 이전 결과 변경 사유와 버전 기록 |
variant별 dispute 수만 비교하지 말고 동일한 분모와 금액 기준을 함께 둡니다. 원거래 수, captured 거래 수, captured 금액 중 무엇을 분모로 쓰는지 명시하고, 부분 dispute와 여러 통화를 어떻게 집계했는지도 적습니다. 표본이 매우 작을 때 퍼센트만 크게 표시하지 않습니다.
8. Primer·Spreedly·Recurly의 기능은 실험 증거와 연결합니다
제품 기능을 채택하는 목적은 “자동 최적화”라는 문구가 아니라 실제 실행 규칙을 추적하는 것입니다. Primer는 A/B testing 안내, Workflows, Observability, Reconciliation을 함께 확인합니다. Spreedly는 Optimize와 Routing and Retry를 기준으로 적용 거래·고정 routing·fallback을 구분합니다. Recurly는 Custom Gateway Routing과 Gateway Failover를 대조해 정상 A/B 배정과 실패 뒤 전환을 분리합니다.
어느 제품이든 거래별 workflow·routing version, 선택 경로, fallback 여부, gateway 응답, 최종 상태와 변경 시각이 export돼야 합니다. 제품 사례의 성능 수치를 현재 merchant의 보장값으로 사용하지 말고 실제 cohort 결과로 검증합니다.
9. 단계별 실행과 중단 조건을 함께 운영합니다
실험은 “시작” 버튼보다 확대 권한을 통제하는 것이 중요합니다. 다음과 같이 단계별 승인 증거를 둡니다. 각 단계의 거래량이나 기간은 시스템 규모와 위험도에 맞게 사전 결정하며, 이 글에서 고정 수치로 제시하지 않습니다.
| 단계 | 목적 | 확대 전 확인 | 즉시 중단 후보 |
|---|---|---|---|
| dry run | 배정·로그·대사 흐름 검증 | 실제 요청 없이 variant·metric 연결 재현 | assignment 누락, 민감정보 로그 노출 |
| 제한된 live cohort | 소수의 적격 거래로 실제 end-to-end 확인 | 승인·capture·refund·webhook·대사 연결 | duplicate 의심, 상태 소실, rollback 실패 |
| 단계 확대 | 지역·통화·결제수단별 품질 확인 | guardrail과 운영 queue 안정 | 오류 급증, processor 상태 불명, 지원 부하 |
| routing 종료 | 신규 배정을 멈추고 결과 성숙 | 미처리 payment와 webhook 정리 | 대사 미완료 상태에서 승자 확정 |
| 최종 검토 | 비용·dispute 포함 결과 승인 | 결측·제외·변경 이력 서명 | 분모 불일치, 비용 범위 미확정 |
중단 조건은 “통계적으로 불리해 보일 때”만이 아닙니다. 다음 운영 조건은 결과 수치와 별도로 확인합니다.
- 같은 order·invoice에 중복 payment가 생성될 가능성
- timeout 뒤 원문 상태 확인 없이 새 processor에 재요청된 흔적
- variant 또는 routing version이 없는 거래 발생
- webhook backlog·순서 역전으로 내부 상태를 신뢰할 수 없는 구간
- 환불·취소를 양쪽 processor에서 일관되게 실행할 수 없는 상태
- balance transaction 또는 payout과 연결되지 않는 거래 증가
- 지원팀이 variant를 확인하지 못해 고객에게 상충된 안내를 하는 상황
- 의도하지 않은 지역·결제수단·기존 token 고객이 cohort에 유입된 상황
이상 징후가 보이면 자동 재시도를 늘리지 말고 신규 실험 배정을 제한한 뒤 processor 원문 상태를 확인합니다. 장애 상황의 상태 재조회와 queue 복구는 결제 공급사 장애 대응 체크리스트를 적용하세요.
10. rollback은 데이터와 결제 action을 따로 되돌립니다
rollback은 feature flag를 끄는 한 줄로 끝나지 않습니다. 신규 라우팅을 원래 경로로 돌리는 일과 이미 B에서 생성된 payment를 안전하게 마무리하는 일을 분리합니다.
rollback runbook
- 신규 eligible 거래의 B 배정을 중지하고 적용 시각과 routing version을 기록합니다.
- 이미 B에서
processing,requires_action,authorized등 미완료 상태인 payment 목록을 고정합니다. - 각 payment의 processor 원문 상태를 조회하고 capture·cancel·고객 동작 여부를 분류합니다.
- 동일 order·invoice를 A에 다시 보내기 전에 기존 action의 최종 상태와 멱등 연결을 확인합니다.
- 지연 webhook과 내부 queue를 폐기하지 말고 중복 없이 반영할 규칙을 적용합니다.
- refund·dispute·payout·fee 자료는 실험 종료 뒤에도 원래 variant에 귀속합니다.
- assignment와 결과 데이터는 삭제하지 않고
stopped_reason,stopped_at,rollback_version을 남깁니다. - 재개하려면 기존 실험을 조용히 수정하지 말고 변경된 cohort·metric·routing에 새 버전을 부여합니다.
rollback 뒤에도 B에서 승인된 거래를 무조건 A로 다시 청구하지 않습니다. 고객 화면이 실패로 보였다는 이유만으로 결제 상태를 추정하면 중복 action 위험이 있습니다. 원문 상태 확인, 내부 order 상태, 후속 capture·cancel 권한을 담당자가 검토해야 합니다.
11. 결과표는 비율보다 분모·결측·관찰 창을 먼저 보여줍니다
다음 표는 최종 보고서 템플릿입니다. 숫자는 실제 export와 대사 자료에서 채우고, 불확실한 항목은 0이 아니라 미확정 또는 결측으로 표시합니다.
실행 품질 표
| 항목 | A | B | 확인 메모 |
|---|---|---|---|
| assigned eligible orders | cohort version과 배정키 | ||
| submitted payment attempts | order당 attempt 분포 | ||
| assignment 누락 | 누락 사유와 영향 | ||
| excluded after assignment | 사후 제외를 최소화하고 사유 공개 | ||
| primary가 아닌 fallback attempts | 독립 A/B 결과에서 분리 | ||
| processor 상태 미확정 | 마지막 원문 조회 시각 | ||
| duplicate suspected | order·invoice별 조사 결과 | ||
| reconciliation exceptions | balance·payout 연결 여부 |
결제 결과 표
| metric | A 분자/분모 | B 분자/분모 | 차이 | 상태 |
|---|---|---|---|---|
| authorization rate | 잠정/확정 | |||
| end-to-end capture rate | 잠정/확정 | |||
| unique order completion rate | 잠정/확정 | |||
| customer-action-required 비중 | 원문 상태 mapping 버전 | |||
| processing error 비중 | processor 원문 code 포함 | |||
| p50·p95 관찰 latency | 측정 시작·종료 지점 명시 |
latency percentile은 측정 지점이 같을 때만 비교합니다. client checkout 시작부터인지, 서버가 processor 요청을 보낸 때부터인지, 최종 webhook까지인지 명시해야 합니다. 평균만으로 긴 지연 구간을 숨기지 않되, 실제 traffic이 적다면 percentile을 과도하게 해석하지 않습니다.
비용·지연 결과 표
| 항목 | A | B | 포함 범위·관찰 종료일 |
|---|---|---|---|
| captured amount by original currency | 통화를 합치지 않은 원본 | ||
| refund amount | 전액·부분 환불 포함 규칙 | ||
| processor fees observed | fee report 기준 | ||
| FX·기타 명시 조정 | 포함한 line item만 열거 | ||
| dispute count and amount observed | cohort maturity 상태 | ||
| observed net amount | cost scope version | ||
| unresolved financial records | payout·balance 미연결 |
최종 결론에는 다음 문장을 반드시 완성합니다.
> 이 결론은 [cohort_version]과 [routing_version]에 포함된 거래, [metric_dictionary_version]의 정의, [cost_scope_version]에 열거된 비용, [관찰 종료일]까지 도착한 지연 결과에만 적용된다. 제외·결측과 이후 도착하는 조정은 별도 버전에서 재검토한다.
12. 실무 체크리스트
- [ ] A와 B의 지역·통화·결제수단·인증 조건을 맞추고 token 예외군을 분리했다.
- [ ] customer·subscription·order 중 안정적인 배정 단위와 cohort version을 정했다.
- [ ] primary A·primary B·fallback, 원문 상태와 공통 event mapping을 구분했다.
- [ ] authorization·capture·order completion의 분자·분모를 문서화했다.
- [ ] fee·refund·dispute·FX 범위와 지연 관찰 종료일을 정했다.
- [ ] 모든 거래에 experiment·variant·routing version과 processor ID가 기록된다.
- [ ] timeout은 원문 상태를 재조회하고 공격적인 retry를 결과 개선 수단으로 쓰지 않는다.
- [ ] hard decline·3DS·timeout·5xx를 구분하고 교차 processor retry 전에 기존 action과 멱등 범위를 확인한다.
- [ ] incident 구간, webhook backlog, duplicate·대사 예외를 guardrail로 감시한다.
- [ ] 종료 뒤 미완료 payment와 refund·fee·payout·dispute를 원래 variant에 귀속한다.
- [ ] 결과표에 분자·분모·결측·제외·원통화와 cohort maturity를 함께 공개한다.
- [ ] 시작·확대·중단·rollback·최종 채택 승인자와 재검토일을 남겼다.
마무리: 좋은 결제 실험은 승자보다 증거를 남깁니다
결제 라우팅 A/B 테스트의 목적은 특정 processor의 우위를 빠르게 선언하는 것이 아닙니다. 같은 조건의 거래를 재현 가능한 방식으로 배정하고, 원본 상태를 공통 사전으로 변환하고, 승인·capture·순매출을 분리하고, 비용과 지연 dispute까지 같은 결과표에 연결하는 것이 핵심입니다.
결과가 유리하더라도 duplicate, reconciliation exception, 고객 문의 또는 rollback 실패 같은 guardrail을 위반하면 바로 확대할 근거가 되지 않습니다. 반대로 차이가 작더라도 어떤 cohort와 결제수단에서 운영 예외가 생겼는지 명확히 알 수 있다면 다음 실험의 가치 있는 입력이 됩니다.
제품 도입 전에는 결제 오케스트레이션 플랫폼 비교로 범위를 정하고, 결제수단 이식성이 필요하면 결제 토큰 이전 체크리스트를 적용하세요. 금액의 월말 연결은 구독 청구 월말 대사 체크리스트, dispute 후속 운영은 결제 분쟁·차지백 운영 체크리스트로 이어가면 실험 결과가 일회성 dashboard에 머물지 않습니다.
실험 중 개별 결제가 hard decline·3DS·timeout 중 어느 상태인지 분류하고 중복 제출을 막아야 한다면 결제 승인 실패·재시도 가드레일 체크리스트를 함께 확인하세요.
함께 보면 좋은 공식 자료
- Primer – A/B testing in payments
- Primer – A/B test checkout flows and payment routing
- Primer – Workflows
- Primer – Observability
- Primer – Reconciliation
- Spreedly – Optimize
- Spreedly – Routing and Retry
- Spreedly – Guide to Intelligent Payment Routing
- Recurly – Custom Gateway Routing Configuration
- Recurly – Gateway Failover
- Stripe – Declines
- Stripe – Error handling
- Stripe – 3D Secure
- Stripe – Payment Intents
- Stripe – Reports
- Stripe – Balance report
- Stripe – Payout reconciliation
- Stripe – Disputes