ADR-W-013

가맹점 구독 상태는 Stripe Webhook을 단일 진실원(Source of Truth)으로 하여 Supabase와 동기화한다

  • ADR ID: ADR-W-013

  • 상태: Accepted

  • 작성일: 2026-03-02

  • 작성자: YSY

  • 관련 ADR: ADR-T-005, ADR-T-001


1. 배경 (Context)

가맹점 구독은 Stripe 기반으로 처리한다.
구독 상태는 다음 기능에 직접 영향을 준다:

  • 발행 가능 횟수

  • 재발행 간격

  • 자동 발행 기능

  • 통계 범위

  • 관리자 기능 접근 권한

결제 성공/실패/취소/갱신이 정확히 DB에 반영되지 않으면:

  • 유료 기능을 무료로 사용

  • 결제했는데 제한 지속

  • 환불/취소 상태 불일치

  • 운영 분쟁 발생

클라이언트에서 결제 성공 콜백만으로 상태를 갱신하는 것은 신뢰할 수 없다.


2. 결정 (Decision)

Stripe Webhook을 구독 상태의 단일 진실원으로 사용한다.

구독 상태 변경은 다음 흐름을 따른다:

  1. Stripe에서 구독 이벤트 발생

  2. Webhook 수신

  3. 서버에서 서명 검증

  4. Supabase의 subscriptions 테이블 업데이트

  5. merchant 플랜 상태 갱신

클라이언트(웹)는 Stripe 응답을 직접 신뢰하지 않는다.


3. 대안 (Alternatives Considered)

대안 A: 클라이언트 성공 콜백 기반 상태 변경

설명
결제 완료 후 웹에서 DB 업데이트

장점

  • 구현 단순

  • Webhook 설정 불필요

단점

  • 위변조 가능성

  • 네트워크 실패 시 상태 불일치

  • 취소/갱신 이벤트 누락

채택하지 않은 이유
결제 상태는 서버 검증이 필수다.


대안 B: Stripe API Polling 방식

설명
주기적으로 Stripe API 호출하여 상태 확인

장점

  • Webhook 없이 동기화 가능

단점

  • 불필요한 API 호출

  • 지연 발생

  • 비용 증가

채택하지 않은 이유
Webhook이 더 정확하고 효율적이다.


대안 C: Stripe Webhook 기반 동기화(채택)

장점

  • 실시간 상태 반영

  • 위변조 방지

  • Stripe 권장 방식

단점

  • Webhook 엔드포인트 관리 필요

  • 서명 검증 로직 구현 필요

채택 이유
결제 상태의 신뢰성과 일관성 확보에 가장 적합하다.


4. 결과 (Consequences)

긍정적 결과

  • 결제 상태 정확성 확보

  • 플랜 권한 일관성 유지

  • 운영 분쟁 감소

  • 서버 중심 권한 통제 가능

부정적 결과

  • Webhook 장애 시 상태 지연

  • 구현 복잡도 증가

  • Stripe 의존성 강화


5. 영향 범위 (Impact)

기술

  • Webhook 엔드포인트 구현(Cloudflare Worker 또는 서버 함수)

  • Stripe 서명 검증 필수

  • subscriptions 테이블 상태 필드 정의 필요:

    • active

    • past_due

    • canceled

    • incomplete

    • trialing

운영

  • Webhook 실패 모니터링 필요

  • 수동 재동기화 도구 고려(관리자용)

UX

  • 플랜 상태는 서버 기준 표시

  • 결제 직후 UI는 “처리 중” 상태를 허용


6. 재검토 조건 (Revisit Conditions)

  • Stripe 외 결제 수단 추가

  • 자체 PG 전환

  • 다중 통화/복합 요금제 구조 도입

  • 구독 모델이 대폭 변경될 경우