Stripe로 구독을 추가하는 방법: 요금제, 체험 기간, 웹훅, 결제 실패 처리
Stripe로 구독을 추가하려면 Stripe 대시보드에서 반복 가격이 있는 상품을 만들고, 서버에서 구독 모드의 Stripe 체크아웃으로 고객을 보내고, 웹훅으로 각 결제가 성공하거나 실패하거나 변경되거나 끝날 때마다 앱이 알 수 있게 하세요. 사용자별로 구독 상태를 저장하고, 접근 권한은 그 상태를 기준으로 주세요. 결제 완료 페이지를 기준으로 하면 안 됩니다. 또한 결제 관리 버튼을 추가해 Stripe가 호스팅하는 고객 포털로 연결하세요. 그러면 사람들이 카드를 바꾸고, 요금제를 바꾸고, 해지하는 화면을 직접 만들지 않아도 됩니다.
이 가이드는 앱에 결제를 추가하는 방법을 바탕으로 하며, 그 가이드는 일회성 체크아웃, 테스트 모드, 실서비스 전환을 다룹니다. 여기서는 정기 결제의 차이점에 집중합니다. Stripe 세부 내용은 2026년 9월 기준 Stripe 문서를 따랐습니다.
구독이 일회성 결제보다 어려운 이유
일회성 결제는 고객이 앱 안에 있을 때 일어납니다. 구독은 고객이 앱을 떠난 뒤에도 계속 일어납니다. 매달 갱신되고, 카드가 만료되고, 주기 중간에 업그레이드하고, 해지는 주기가 끝날 때 적용됩니다. 앱은 이런 일을 웹훅으로만 알게 됩니다. 대부분의 구독 버그는 첫 결제를 전체 이야기로 취급하는 데서 생깁니다.
선택지
| 방식 | 직접 만들어야 하는 것 | 적합한 경우 |
|---|---|---|
| 반복 가격이 있는 결제 링크 | 링크 하나뿐 | 수요 테스트, 접근 권한을 직접 관리할 때 |
| 체크아웃(구독 모드) + 고객 포털 | 서버 라우트, 웹훅, 결제 관리 버튼 | 대부분의 SaaS 앱과 멤버십 |
| 구독 API + 직접 만든 결제 양식 | 훨씬 많음: 결제 UI, 인증, 재시도 | 특이한 결제 흐름이 필요한 앱 |
| 판매 대행자(merchant of record) 제공업체 | 체크아웃과 비슷함 | 판매세 처리를 제공업체에 맡기려는 판매자 |
대부분의 앱에는 체크아웃과 포털 조합이 합리적인 선택입니다. 세금 처리가 걱정된다면 Stripe vs Paddle vs Lemon Squeezy에서 제공업체를 비교해 보세요.
먼저 Stripe에서 가격 설계하기
Stripe에서 상품은 판매하는 것("Pro 요금제")이고, 가격은 그것을 얼마에 청구하는지("월 $20", "연 $200")입니다. 상품 하나에 가격 여러 개를 둘 수 있습니다. 다음을 정하세요.
- 어떤 등급을 제공하고, 각 등급이 앱에서 무엇을 여는지
- 월간, 연간, 또는 둘 다
- 체험 기간을 제공할지, 그리고 카드를 미리 받을지
상품과 가격은 테스트 모드에서 만들고, 그 가격 ID를 기록해 두세요. 앱은 그 ID로 상품을 참조합니다. 가격이 아직 정해지지 않았다면 SaaS 제품 가격 책정 방법과 프리미엄과 무료 체험 비교를 읽어 보세요.
처리해야 할 구독 수명 주기
Stripe의 구독 개요는 구독이 가질 수 있는 상태를 나열합니다. 접근 권한과 가장 관련 있는 상태는 다음과 같습니다.
| 상태 | 의미 | 접근 권한 부여? |
|---|---|---|
trialing | 체험 기간 중 | 예 |
active | 정상 상태 | 예 |
incomplete | 첫 결제가 아직 완료되지 않음. Stripe는 고객에게 23시간을 줍니다 | 아니요 |
incomplete_expired | 첫 결제가 끝내 성공하지 못함 | 아니요 |
past_due | 최근 결제가 실패했거나 시도되지 않음. 재시도가 이어질 수 있음 | 정책에 따라 다름. 많은 앱이 짧은 유예 기간을 둡니다 |
unpaid | 재시도가 끝나고 인보이스가 미결제 상태로 남으며, 더 이상 시도하지 않음 | 아니요. Stripe 문서는 접근 권한을 취소하라고 설명합니다 |
canceled | 종료됨. 다시 시작할 수 없음 | 아니요 |
paused | 결제 수단 없이 체험이 끝났고 일시 중지로 설정됨 | 아니요 |
사용자 또는 계정 레코드에 상태를 저장하고, 접근 권한을 그 상태에 근거하세요. 관련 웹훅이 도착할 때마다 상태를 업데이트하세요.
처리해야 할 웹훅 이벤트
| 이벤트 | 앱이 하는 일 |
|---|---|
checkout.session.completed | 새 Stripe 고객 ID와 구독 ID를 사용자와 연결 |
invoice.paid | 구독을 활성 상태로 표시하고 새 기간 종료일을 기록 |
invoice.payment_failed | 카드 결제가 실패했음을 알리고 포털 링크 제공 |
invoice.payment_action_required | 사용자에게 카드 인증 완료를 요청 |
customer.subscription.updated | 요금제, 상태, 예약된 해지 업데이트 |
customer.subscription.deleted | 유료 접근 권한 제거 |
customer.subscription.trial_will_end | 체험이 끝나기 전에 사용자에게 알림. Stripe는 3일 전에 보냅니다 |
Stripe 웹훅 문서의 처리기 규칙도 그대로 적용됩니다. 원본 본문으로 서명을 검증하고, 2xx 응답을 빠르게 반환하고, 중복 및 순서가 뒤바뀐 이벤트를 처리하고, 재시도를 예상하세요. 웹훅이란에서 개념을 설명하고, 결제 가이드에서 규칙을 자세히 다룹니다.
단계별 진행
- Stripe 테스트 모드에서 상품과 가격을 만드세요.
- 시크릿을 추가하세요. 비밀 키, 가격 ID, 나중에는 웹훅 서명 비밀을 넣습니다. 프런트엔드 코드에는 절대 넣지 마세요.
- 가격 페이지: 각 요금제 버튼이 서버를 호출하고, 서버가 로그인한 사용자를 위해 구독 모드 체크아웃 세션을 만듭니다. 웹훅이 결제를 계정과 맞출 수 있도록 사용자 ID를 함께 넘기세요.
- 웹훅 엔드포인트: 서명을 검증하고 위의 이벤트를 처리하며, 사용자마다 구독 레코드 하나를 업데이트합니다.
- 기능 접근을 제한하세요. 저장된 상태와 요금제를 기준으로 하며, 버튼만 숨기는 것이 아니라 보호되는 모든 작업마다 서버에서 확인하세요.
- 고객 포털: Stripe 대시보드에서 설정합니다(사용자가 바꿀 수 있는 요금제, 해지 허용 여부 등). 그다음 서버에서 포털 세션을 만들고 그곳으로 리디렉션하는 "결제 관리" 버튼을 추가하세요.
- 결제 실패: Stripe 결제 설정에서 재시도 방식과 마지막 재시도 이후의 동작을 고르세요.
past_due상태 동안에는 앱 안에 배너를 보여 주세요. - 전체 수명 주기를 테스트하고, 게시한 뒤 실서비스 웹훅을 등록하세요.
AI 빌더에 줄 프롬프트
Stripe로 구독 결제를 추가해 주세요. 요금제는 Starter(가격 ID는 STRIPE_PRICE_STARTER)와 Pro(STRIPE_PRICE_PRO)입니다. 가격 페이지는 서버에서 STRIPE_SECRET_KEY를 사용해 구독 모드 체크아웃 세션을 만들고, 로그인한 사용자의 ID를 붙여 주세요. Stripe 고객 ID, 구독 ID, 요금제, 상태를 사용자 레코드에 저장해 주세요. 비밀 키는 절대 브라우저에 노출하지 마세요.
POST /api/stripe/webhook을 추가해 주세요. STRIPE_WEBHOOK_SECRET으로 원본 요청 본문을 사용해 서명을 검증하세요. checkout.session.completed, invoice.paid, invoice.payment_failed, customer.subscription.updated, customer.subscription.deleted, customer.subscription.trial_will_end를 처리하세요. 처리한 이벤트 ID를 기록해서 중복을 무시하게 해 주세요. 사용자 상태는 이벤트가 도착한 순서가 아니라 구독 객체를 기준으로 업데이트해 주세요.
서버에서 Pro 기능을 제한해 주세요. 상태가 active 또는 trialing이고 요금제가 Pro일 때만 허용합니다. 상태가 past_due이면 "결제 실패, 카드를 업데이트하세요" 배너를 보여 주세요. 이 사용자를 위해 Stripe 고객 포털을 여는 결제 관리 버튼을 추가해 주세요.
업그레이드, 다운그레이드, 일할 계산
고객이 요금제를 바꾸면, Stripe 문서에 따르면 변경으로 보통 **일할 계산(proration)**이 생깁니다. 새 가격이 현재 청구 기간의 남은 기간에 적용되는 것입니다. 일할 계산을 미리 보거나 끌 수 있습니다. 두 요금제의 주기가 같다면 청구일은 그대로 유지됩니다. 월간에서 연간으로 바꾸면 청구일이 전환한 날로 옮겨집니다. 고객이 포털에서 요금제를 바꾸게 하면 이 로직을 직접 쓸 필요가 줄어듭니다. 다만 포털 설정에서 어떤 전환을 허용할지는 정해야 합니다.
테스트 체크리스트
Stripe 테스트 모드와 테스트 카드를 사용해 모든 상태를 확인하세요.
- 새 구독이 올바른 사용자에게 올바른 요금제를 부여한다
- 결제 직후 탭을 닫아도 접근 권한이 생긴다(웹훅이 동작한다는 증명입니다)
- 가입 시 카드가 거절되면 아무 권한도 부여되지 않는다
- 실패한 갱신은 계정을
past_due로 두고 배너를 보여 준다 - 포털에서 카드를 업데이트하면
active상태가 복원된다 - 업그레이드와 다운그레이드가 기능을 올바르게 바꾼다
- 주기 말 해지는 종료일까지 접근을 유지하고, 그 뒤에 제거한다
- 체험 사용자는 접근할 수 있고, 알림을 받으며, 전환하거나 접근을 잃는다
- 같은 웹훅 이벤트를 두 번 보내도 아무것도 바뀌지 않는다
Stripe의 테스트 클록을 쓰면 시간이 흐르는 것을 시뮬레이션할 수 있어서, 한 달을 기다리지 않고 갱신을 테스트할 수 있습니다. 사용 방법은 Stripe의 최신 테스트 문서를 확인하세요.
흔한 실수
- 결제 완료 페이지에서 접근 권한 부여. 고객이 결제하고도 그 페이지에 도달하지 못할 수 있습니다. 웹훅을 쓰세요.
- 첫 결제만 처리. 갱신, 실패, 해지는 나중에 이벤트로 도착합니다.
- 프런트엔드에서만 요금제 상태 확인. 누구나 API를 직접 호출할 수 있습니다.
- 실수로 한 사용자에게 구독이 여러 개 생김. 새 체크아웃 세션을 만들기 전에 기존 구독이 있는지 확인하거나, 기존 고객은 포털로 보내세요.
- 첫 갱신 실패에 바로 접근 권한 취소. 카드는 평범한 이유로 실패합니다. 짧은 유예 기간과 명확한 배너가 고객을 지켜 줍니다.
- 실서비스 웹훅을 잊음. 테스트와 실서비스 엔드포인트는 서로 다른 서명 비밀을 가집니다.
- 세금과 환불을 무시함. 출시 전에 환불 정책을 정하고, 세금 의무는 회계사와 확인하세요.
Mythex의 구독
Mythex로 만든 앱은 여러분 자신의 Stripe 계정과 키를 사용합니다. 앱을 위한 원클릭 Stripe 연결은 없습니다. 테스트 키와 가격 ID를 프로젝트 시크릿으로 추가하고, 위와 같은 프롬프트를 쓰고, 미리보기에서 Stripe 테스트 카드로 테스트하세요. 웹훅에는 앱의 공개 URL이 필요하므로, Stripe에 엔드포인트를 등록하기 전에 게시하고, 실서비스 키로 바꾼 뒤에는 실서비스 앱이 새 키를 쓰도록 다시 게시하세요. 자세한 내용은 Stripe로 결제 받기와 백엔드에서 웹훅 처리하기를 참고하세요. 구독 주변에 어떤 기능을 만들어야 할지는 SaaS MVP 만드는 법에서 다룹니다.
자주 묻는 질문
Stripe로 구독을 추가하는 가장 간단한 방법은 무엇인가요?
Stripe 대시보드에서 반복 가격이 있는 상품을 만들고, 고객을 구독 모드의 Stripe 체크아웃으로 보내고, 구독 이벤트는 웹훅으로 처리하고, '결제 관리' 버튼은 Stripe가 호스팅하는 고객 포털에 연결하세요. 그러면 카드 입력 양식과 요금제 변경 화면을 직접 만들 필요가 없습니다.
구독에 필요한 Stripe 웹훅 이벤트는 무엇인가요?
최소한 새 구독을 사용자와 연결하는 checkout.session.completed, 매 결제 성공을 확인하는 invoice.paid, 갱신 실패를 알리는 invoice.payment_failed, 요금제 변경과 해지를 추적하는 customer.subscription.updated와 customer.subscription.deleted가 필요합니다.
구독 결제가 실패하면 어떻게 되나요?
Stripe 문서(2026년 9월 기준)에 따르면, 보통 구독은 past_due 상태가 되고 Stripe는 설정에 따라 결제를 재시도할 수 있습니다. 마지막 재시도 후에는 대시보드 설정에 따라 구독이 취소되거나, unpaid로 표시되거나, past_due 상태로 남습니다.
카드 정보를 받지 않고 무료 체험을 제공할 수 있나요?
네. Stripe는 무료 체험을 지원하며, 문서에는 결제 수단 없이 체험이 끝났을 때 설정에 따라 일시 중지되는 paused 상태도 설명되어 있습니다. 체험 시작 시 카드를 받으면 보통 가입자는 줄지만 유료 고객은 늘어납니다. 제품에 맞는 방식을 테스트해 보세요.