핵심 요약
- 유령 주문의 원인은 결제 결과를 고객 브라우저(프론트엔드 Callback)에 의존하기 때문이에요. 브라우저 이탈, 네트워크 단절, 앱 강제 종료 시 결제 데이터가 증발해요.
- '결제 버튼 클릭 시 대기 상태 주문 생성'과 '웹훅(서버 간 통신) 기반 상태 확정' 두 원칙만 지키면 결제-주문 불일치 사고의 99%를 예방해요.
- 유령 주문이 실제 발생했을 때는 PG 관리자에서 거래 확인 → 웹훅 재전송 → 주문 강제 매칭 → 고객 안내 순서로 대응하고, 배치 프로그램으로 10분 이상 대기 중인 건을 자동 감지하는 구조를 갖춰야 재발을 막아요.
1돈은 나갔는데 주문이 없는 이유: 프론트엔드 리다이렉트의 맹점
결제 데이터가 어긋나는 근본 원인은 서버 간 통신이 아닌 '고객의 브라우저' 응답에 의존하기 때문이에요. 결제 시스템은 고객 브라우저, 서비스 서버, PG사 서버라는 세 지점을 거치는데, 브라우저는 가장 불안정한 연결 고리예요.
프론트엔드 리다이렉트(Callback)의 한계
많은 팀이 처음 결제를 연동할 때, 고객이 결제창에서 '확인'을 누른 뒤 돌아오는 결과 데이터(Callback)를 받아 주문을 생성해요. 하지만 아래 상황에서는 데이터가 증발해요.
- 네트워크 단절: 결제는 완료됐으나 서비스 페이지로 돌아오는 도중 와이파이가 끊기는 경우.
- 사용자 이탈: 결제 완료 팝업을 보자마자 '뒤로 가기'를 누르거나 브라우저 탭을 닫는 경우.
- 앱 강제 종료: 모바일 인앱 브라우저에서 결제 후 앱이 리프레시되면서 응답값을 놓치는 경우.
이 경우 PG사 전산에는 '성공'으로 기록되지만, 서비스 서버는 그 소식을 듣지 못해요. 결국 돈은 받았으나 물건을 보내주지 않는 최악의 CS 상황이 만들어져요.
브라우저 이탈 문제와는 별개로, 극히 드물게는 PG사와 카드사 사이에서 승인 데이터가 누락되는 시스템 레벨 불일치도 존재해요. 확률적으로는 0.001% 미만인 희귀 케이스지만, 카드사에서는 승인이 났는데 PG사로 전달되는 과정에서 네트워크 이슈로 데이터가 유실되면 서비스와 PG 양쪽 모두 거래를 놓칠 수 있어요. 발생 확률은 매우 낮아도 거래량이 많아지면 월 단위로 소수 건이 생길 수 있으므로, 3장에서 설명하는 배치 대조 로직은 이런 케이스까지 감지할 수 있어야 해요.
2유령 주문을 원천 봉쇄하는 주문 상태 전이 설계
결제가 완전히 끝나고 주문을 만드는 것이 아니라, 결제 시작 시점에 '대기' 상태 주문을 미리 생성해 데이터 연결 고리를 확보해요. 기획 단계에서 주문 데이터 생성 시점을 결제 버튼 클릭 시점으로 앞당겨야 해요.
결제-주문 상태 전이 모델
- 결제 대기(Pending): 고객이 결제 버튼을 누르는 순간 주문 번호를 생성하고 DB에 기록해요. 이때는 아직 재고를 차감하지 않아요.
- 결제 완료(Success): 서비스 서버가 웹훅(Webhook)을 통해 PG사로부터 성공 신호를 받았을 때만 이 상태로 바꿔요. 이때 재고를 차감하고 확정 문자를 보내요.
- 결제 실패/취소(Failed/Canceled): 일정 시간(예: 30분) 내에 성공 신호가 오지 않으면 대기 상태의 주문을 자동 무효화해요.
개발자와 논의할 때는 "웹훅을 기반으로 주문 상태를 최종 확정한다"는 원칙을 먼저 정해야 해요. 웹훅은 서버와 서버가 직접 통신하므로 고객이 브라우저를 닫아도 데이터가 유실되지 않아요.
3시스템 안정성을 높이는 3가지 기술적 체크포인트
단순한 연동을 넘어 예외 상황에서도 데이터 정합성을 유지하는 장치가 필요해요. 다음 세 가지 포인트를 시스템 설계에 반영해요.
브라우저 결과값보다 웹훅을 우선해요
프론트엔드에서 받은 결제 결과는 오직 '고객에게 보여줄 화면'용으로만 사용해요. 실제 주문을 확정하고 재고를 깎는 무거운 로직은 서버에서 받은 웹훅 데이터를 기준으로 처리해요. 똑같은 결제 신호가 두 번 와도 주문이 중복 생성되지 않도록 멱등성(Idempotency) 처리가 되어 있는지 확인해야 해요.
상태 불일치 자동 감지 로직을 둬요
PG사 장애로 웹훅이 늦게 올 가능성에 대비해 '결제는 됐으나 주문 상태가 대기인 건'을 주기적으로 찾아내는 모니터링 기준을 세워요. 생성된 지 10분이 지났는데 아직 '대기' 상태인 주문 중 PG사 전산에서 '성공'인 건이 있는지 배치(Batch) 프로그램으로 자동 대조하는 식이에요.
결제 실패 및 지연 안내 문구를 세분화해요
단순히 "결제 실패"라고만 노출하면 고객은 중복 결제를 시도하거나 이탈해요.
- 진짜 실패: "잔액 부족으로 결제되지 않았습니예요. 다시 시도해주세요."
- 처리 지연: "결제 처리가 지연되고 있어요. 1~2분 뒤 주문 내역에서 확인해주세요." 상태 처리가 늦어지는 경우 고객이 안심하고 기다릴 수 있도록 가이드하는 것이 기획자의 역할이에요.
카카오페이, 네이버페이 같은 충전형 간편결제에서는 고객이 결제를 시도하면 먼저 연결된 카드에서 간편결제 포인트로 충전이 일어나요. 이 시점에 카드사에서 출금 문자가 오기 때문에 고객은 가맹점 결제가 완료된 것으로 받아들이기 쉬워요. 하지만 충전 이후 실제 가맹점 결제 승인 단계에서 네트워크 오류나 타임아웃이 발생하면, 카드에서 돈은 빠졌지만 그 금액은 간편결제 잔액으로 남고 가맹점에는 결제가 안 된 상태가 돼요. 이것은 유령 주문이 아니에요. 고객 손실이 발생한 것이 아니라 충전된 잔액이 남아 있는 상태이기 때문이에요. CS에서는 "카드에서 빠졌는데 주문이 없어요"라는 문의가 들어오면 먼저 카카오페이나 네이버페이 잔액을 확인해달라고 안내해야 해요. PG 관리자에서 해당 거래가 조회되지 않는다면 이 케이스일 가능성이 높아요.
운영 사고 즉시 해결을 위한 '유령 주문' 대응 플레이북
운영 중에 실제 유령 주문 문의가 들어왔을 때, 팀 전체가 즉시 실행할 행동 지침이에요.
1단계: 사실 확인 (운영 담당자)
- 고객의 결제 수단과 결제 시각 확인
- PG사 관리자 화면에서 해당 거래가 '성공'인지 확인 (이미 취소된 거래라면 취소 상태임을 안내)
2단계: 데이터 강제 매칭 (기획자/개발자)
- 서버 로그에서 웹훅 수신 여부 확인
- 웹훅이 오지 않았다면 PG사 관리자에서 수동으로 '웹훅 재전송' 실행
- 주문 상태를 '결제 완료'로 강제 변경하고 재고 차감 로직 실행
3단계: 고객 안내 (CS 담당자)
- "결제 데이터 처리 과정에서 일시적인 지연이 발생했어요. 주문이 정상 접수되었음을 확인했어요."
- 만약 재고가 부족해 주문 처리가 불가능하다면 즉시 카드 취소(PG 전산 취소) 처리 후 사과 메시지를 발송해요.
다음 단계
주문 누락 대응 방식을 정했다면, 이제 결제 완료 기준과 운영 루틴을 묶어 정산 사고까지 막는 구조를 만들어야 해요.
추천 콘텐츠
결제 상태 매핑: 7가지 상태값과 완료 확정 원칙 결제 완료는 서버가 주문 상태를 확정한 순간임을 기준으로 상태값과 흐름을 맞춰요.
결제 사고 90% 줄이는 운영자용 일일·주간·월간 체크리스트 라이브 이후 어떤 항목을 정기 점검해야 비슷한 사고를 줄일 수 있는지 확인해요.
바로 참고할 문서
- 개발 문서: 부트페이 웹훅 설정 및 검증 가이드
