Search
💳

결제 승인 API, 어떻게 더 안전하게 만들 수 있을까?

결제 승인 API, 어떻게 더 안전하게 만들 수 있을까?

하입타운의 UX를 지키는 기술적 고민과 개선 이야기
안녕하세요. 하입타운 대표 공태현입니다.
저희는 최근 서비스 전반에 걸쳐 제품 리뉴얼을 진행하고 있으며, 그 과정에서 결제 API를 포함한 전체 API 시스템의 안정성 개선 작업을 함께 수행하고 있습니다.
결제 시스템은 단순한 기능 그 이상입니다.
사용자에게 신뢰를 주는 UX의 핵심이며, 아주 작은 오류 하나가 서비스에 대한 인식 전체를 뒤흔들 수 있습니다.
하입타운은 “쉽고 즐거운 문화 경험”을 제공하는 서비스지만, 그 안에 담긴 기술은 누구보다 진지하게 다루고 있습니다.
이번 글에서는 저희가 구매 승인 API(Approve Purchase API) 를 점검하며 발견한 잠재적 리스크와 이를 어떻게 기술적으로 해결했는지를 공유드리고자 합니다.

구매승인 API 안정성 개선 및 Grace Period 전략 적용

문제 가정 및 개선 목적

결제 승인 API(Approve Purchase) 과정에서 다음과 같은 잠재적인 리스크가 식별되었습니다:
사용자 입장에서 결제는 정상적으로 완료됐지만,
내부 시스템에서는 티켓 보류 시간이 만료되어, 해당 티켓이 반환된 상태일 가능성
이로 인해 결제 완료 상태와 실제 티켓 보유 상태 간의 불일치가 발생할 수 있음
이를 방지하기 위해 API 구조를 재정비하고, Grace Period 기반의 안정화 전략을 적용하였습니다.

리스크 시나리오

예시 흐름

1.
사용자가 Apply API를 통해 티켓을 선점 → 내부 시스템은 해당 티켓을 8분간 보류
2.
사용자에게는 6분 결제 타이머만 UI에 노출
3.
사용자가 7분 30초쯤 Approve Purchase API 호출
4.
서버는 Toss Payments에 결제 승인 요청을 보냄
5.
Toss 측에서는 결제를 성공적으로 처리
6.
그러나 내부 시스템에서는 이미 8분 보류 시간이 초과되어, 티켓이 반환된 상태
→ 사용자는 결제를 완료했지만, 내부적으로는 티켓을 보유하지 않은 상태가 되어 정합성 문제가 발생할 수 있음

개선 설계 방향

이러한 리스크를 해소하기 위해, 결제 승인 흐름에서 트랜잭션 안전성과 사용자 경험의 정합성을 동시에 고려한 구조로 개선하였습니다.

핵심 전략: Grace Period Cutoff

사용자에게는 6분 결제 타이머만 표시
내부 시스템은 8분간 티켓을 보류하며, 유예 시간을 확보
Approve Purchase API 호출 시점에 서버 시간 기준 7분을 초과했는지 검사
초과 시 결제 승인 요청을 받지 않고 "세션이 만료되었습니다" 메시지 반환
이로써 1분의 보호 턴(Grace Cutoff)을 두어 트랜잭션 및 외부 요청 경합을 방지

고려했던 방안과 비교

방안
설명
한계
외부 결제 후 내부 처리
Toss 응답을 기반으로 내부 승인 진행
트랜잭션 내 멱등성 보장 어려움, 상태 불일치 가능성
외부 요청 포함한 트랜잭션
승인 API 전체를 트랜잭션으로 처리
Firestore 트랜잭션 자동 재시도와 외부 호출 충돌
결제 승인 시점에 보류 상태 연장
API 호출 시 보류시간을 연장하여 보호
로직 복잡도 상승, 불확실성 잔존
Grace Cutoff 적용
7분 이상 요청은 세션 만료로 간주
사용자 기대와 정합성 모두 확보

Grace Period Cutoff 전략 개념

사용자의 체감 타이머(예: 6분)보다 내부 시스템 보류 시간을 더 길게 설정(예: 8분)하고,
일정 임계 시점(예: 7분 경과)부터는 유효성을 엄격히 제한하는 전략으로,
실시간 처리가 어려운 결제 흐름에서도
정합성과 사용자 신뢰
이 전략은 대규모 결제 시스템(Stripe, Toss 등)에서도 응답 시간, 네트워크 지연, 트랜잭션 경합 등의 현실적인 문제를 고려해 적용되는 사실상 업계 표준 패턴입니다.

이번 개선에서 얻은 인사이트

사용자 타이머와 시스템 보류 시간을 분리하는 구조는 신뢰도 높은 결제 경험을 만드는 핵심 요소
결제 승인 전 반드시 내부 유효성을 서버 트랜잭션 내에서 검증해야 함
외부 API 호출은 트랜잭션 외부에서만 수행해야 함 (재시도 이슈 회피)
Grace Period Cutoff는 복잡한 문제를 단순하고 예측 가능하게 해결할 수 있는 좋은 패턴

향후 계획

Grace Cutoff 기반 유효성 검사 로직 → 트랜잭션 내 구현 완료
승인 실패 시 사용자 피드백 문구 명확화 및 UI 반영
전 흐름에 대한 QA 시나리오 추가 및 테스트 자동화 진행

왜 중요한가?

결제 시스템에서 가장 중요한 것은 결제 성공 = 상품 확보라는 정합성입니다.
Grace Cutoff 전략은 이 정합성을 유지하면서도 사용자 UX를 해치지 않는 방식입니다.
실제로 Stripe, Toss 등 글로벌 결제 서비스에서도 이와 유사한 보호구간 개념을 시스템에 녹여두고 있습니다.

우리가 배운 것들

“발생하지 않은 문제라도, 예측할 수 있다면 예방해야 한다.”
서비스 신뢰는 단순한 SLA가 아니라, 디테일한 시나리오 설계에서 비롯된다는 걸 다시금 느꼈습니다.
사용자 경험을 해치지 않으면서도 안정성을 높이는 방법은 언제나 존재합니다. 다만 그만큼 사려 깊은 설계와 대화가 필요합니다.

마무리하며

하입타운은 앞으로도 단순히 “기능이 동작하는 것”을 넘어,
사용자가 신뢰할 수 있는 기술예상 가능한 흐름을 만들어가겠습니다.
지금도 보이지 않는 곳에서, 더 나은 UX를 위해 계속해서 고민하고 개선 중입니다.
이러한 이야기들이 도움이 되셨다면, 다음에도 저희의 기술적 인사이트를 공유드리겠습니다.