결제가 붙는 순간 제품의 질문이 바뀐다
지금까지 우리는 소상공인 리뷰를 업로드하고, AI가 분석하고, 사장님이 읽을 수 있는 리포트 화면까지 만들었다. 여기까지는 '쓸 만한가'를 확인하는 단계다. 결제를 붙이면 질문이 바뀐다.
'돈을 낼 만큼 중요한가?'
이 질문은 개발자가 코드 안에서 답할 수 없다. 가격표를 보여주고, 결제 버튼을 누르게 하고, 성공·실패·환불·취소 상태를 실제 권한에 반영해야 답이 나온다. 그래서 결제는 마지막에 붙이는 장식이 아니다. 서비스가 사업으로 바뀌는 경계선이다.
다만 첫 결제 설계를 너무 크게 만들면 위험하다. 구독, 쿠폰, 팀 결제, 세금계산서, 사용량 과금, 환불 자동화, 관리자 정산 화면을 한 번에 만들면 정작 가격 검증은 늦어진다. 1인 창업가의 첫 목표는 완성된 빌링 시스템이 아니라, 고객이 어떤 제안에 돈을 내는지 확인하는 것이다.
우리 서비스의 첫 결제 가설은 이렇게 잡는다.
무료 샘플 리포트: 가입 전 신뢰 형성용
1회 분석권: 첫 유료 전환 검증용
월 구독 플랜: 반복 사용 가능성이 확인된 뒤 확장
처음부터 월 구독만 밀어붙이지 않는다. 음식점·카페 사장님 입장에서는 아직 이 서비스가 매달 필요한지 알 수 없다. 반면 '우리 매장 리뷰 50개를 분석한 리포트 1회'는 이해하기 쉽다. 구매 후 결과도 바로 확인할 수 있다.
AI 생성 이미지
첫 가격 구조는 낮은 진입 장벽부터
가격 구조를 설계할 때는 우리가 팔고 싶은 방식보다 고객이 처음 결제하기 쉬운 방식을 먼저 봐야 한다. 예제 서비스에서 선택지는 세 가지다.
| 방식 | 고객이 느끼는 장점 | 창업가가 얻는 신호 | 주의할 점 |
|---|---|---|---|
| 무료 샘플 리포트 | 가입 전 결과물을 볼 수 있다 | 문구와 리포트 이해도를 확인한다 | 실제 매장 데이터가 아니면 구매 신호가 약하다 |
| 1회 분석권 | 부담 없이 한 번 써볼 수 있다 | 돈을 낼 문제인지 확인한다 | 반복 매출은 아직 검증되지 않는다 |
| 월 구독 | 매달 리뷰 관리가 가능하다 | 지속 사용 의향을 본다 | 첫 구매 장벽이 높다 |
초기에는 '무료 샘플 리포트 + 1회 분석권'을 기본으로 둔다. 샘플 리포트는 랜딩페이지와 가입 후 빈 대시보드에서 보여준다. 고객은 결제 전에 결과물의 형태를 본다. 1회 분석권은 실제 리뷰를 업로드한 뒤, 미리보기 화면에서 결제하도록 만든다.
흐름은 다음과 같다.
사용자가 매장 정보를 입력한다.
리뷰를 붙여넣거나 CSV로 업로드한다.
업로드 미리보기에서 분석 가능 리뷰 수를 확인한다.
'AI 리포트 생성하기' 버튼을 누른다.
무료 사용권이 없으면 결제 화면으로 이동한다.
결제 성공을 서버에서 확인한 뒤 분석권을 부여한다.
사용자가 분석 실행을 확정하면
analysis_job을 생성한다.분석이 완료되면 리포트를 열람할 수 있게 한다.
중요한 점은 결제 전에 AI API를 호출하지 않는 것이다. 업로드만으로 분석을 자동 시작하면 비용 통제가 어렵다. 사용자가 결제하거나 무료 크레딧을 사용하기로 확정한 뒤에 작업을 생성한다.
첫 가격은 복잡할 필요가 없다.
| 상품 | 가격 가설 | 제공 내용 |
|---|---|---|
| 무료 샘플 | 0원 | 데모 매장의 샘플 리포트 열람 |
| 1회 분석권 | 39,000원 | 리뷰 최대 100개 분석, 리포트 1개 생성, 공유 링크 제공 |
| 월 구독 | 99,000원 | 월 4회 분석, 과거 리포트 보관, 답글·홍보 문구 재생성 |
여기서 가격은 정답이 아니라 실험값이다. 39,000원이 높을 수도 있고 낮을 수도 있다. 중요한 것은 고객이 비싸다고 말하는지, 결제 직전에서 멈추는지, 결제 후 다시 쓰고 싶어 하는지를 기록하는 것이다.
결제 도구는 고객 위치와 운영 부담으로 고른다
결제 도구는 기능표만 보고 고르면 안 된다. 1인 창업가에게 더 중요한 기준은 세 가지다.
첫 고객이 한국 고객인가, 해외 고객인가
세금과 정산 업무를 어디까지 직접 감당할 것인가
구독, 환불, 취소 상태를 얼마나 세밀하게 제어해야 하는가
한국 음식점·카페 사장님을 먼저 대상으로 한다면 TossPayments가 자연스럽다. 국내 고객에게 익숙한 카드, 계좌이체, 가상계좌, 휴대폰 결제 같은 수단을 고려할 수 있고, 가상계좌처럼 입금이 나중에 확정되는 결제는 웹훅으로 상태 변경을 받아 주문 상태를 맞출 수 있다1. 국내 결제 경험의 마찰을 줄이는 데 유리하다.
해외 고객까지 처음부터 판매한다면 Stripe나 Lemon Squeezy를 검토한다. Stripe는 결제 화면과 구독 로직을 세밀하게 제어하기 좋고, 복잡한 과금 모델에도 강하다. 대신 Stripe Tax 같은 기능을 별도로 사용하더라도, 판매 국가별 세금 등록·신고·환불·분쟁 대응에서 운영자가 책임져야 할 범위가 어디까지인지 확인해야 한다. Lemon Squeezy는 Merchant of Record 방식으로 세금 계산·징수·신고, 환불과 차지백 처리 부담을 줄여주는 대신 수수료가 더 높고 결제 경험의 자유도는 낮을 수 있다2. Merchant of Record는 고객에게 법적으로 판매하는 주체가 결제 플랫폼이 되는 구조를 뜻한다.
간단히 정리하면 다음과 같다.
| 도구 | 먼저 고려할 상황 | 장점 | 주의할 점 |
|---|---|---|---|
| TossPayments | 한국 고객 중심 | 국내 결제 수단과 한국식 결제 흐름에 익숙하다 | 해외 SaaS 판매와 글로벌 세금 처리는 별도 검토가 필요하다 |
| Stripe | 해외 판매, 복잡한 구독, 높은 제어권 | API와 구독 기능이 강하고 확장성이 좋다 | 세금·분쟁·환불 운영 책임을 직접 확인해야 한다 |
| Lemon Squeezy | 글로벌 판매를 빠르게 열고 싶은 1인 창업가 | Merchant of Record 구조로 세금·결제 운영 부담을 줄일 수 있다 | 수수료가 높고 커스터마이징 한계가 있을 수 있다 |
이 책의 예제 서비스는 한국의 음식점·카페 사장님을 1차 고객으로 잡았다. 따라서 첫 유료 실험은 TossPayments로 1회 분석권을 붙이는 선택이 현실적이다. 해외 리뷰 플랫폼을 대상으로 확장하거나 영어권 소상공인을 타깃으로 바꿀 때 Stripe나 Lemon Squeezy를 다시 비교한다.
결제 상태와 서비스 권한을 분리해서 저장한다
결제 연동에서 흔한 실수는 '결제 성공 페이지에 도착했으니 권한을 열어준다'고 처리하는 것이다. 성공 페이지는 사용자의 브라우저 이동일 뿐이다. 중간에 브라우저가 닫히거나, 악의적으로 URL을 호출하거나, 비동기 결제 상태가 늦게 바뀔 수 있다.
권한은 반드시 서버에서 확인한 결제 상태와 웹훅 이벤트를 기준으로 바꾼다. 사용자가 성공 페이지로 돌아왔을 때도, 그 페이지의 쿼리 값만 믿지 말고 서버에서 결제 승인 또는 결제 조회를 한 번 더 거쳐야 한다.
Supabase에는 최소한 다음 테이블이 필요하다.
products
- id
- name
- type: one_time | subscription
- price_amount
- currency
- analysis_limit
- review_limit
- active
payments
- id
- user_id
- provider: toss | stripe | lemon_squeezy
- provider_payment_id
- provider_order_id
- product_id
- amount
- currency
- status: pending | paid | failed | refunded | partially_refunded | canceled
- created_at
- paid_at
payment_events
- id
- provider
- provider_event_id
- provider_payment_id
- event_type
- received_at
- processed_at
entitlements
- id
- user_id
- store_id
- source_type: payment | coupon | manual
- source_payment_id
- type: analysis_credit | subscription
- remaining_count
- review_limit
- status: active | used | expired | revoked
- starts_at
- ends_at
subscriptions
- id
- user_id
- provider
- provider_subscription_id
- plan_id
- status: active | past_due | canceled | unpaid
- current_period_start
- current_period_endpayments는 돈의 기록이다. entitlements는 서비스 이용 권한이다. 이 둘을 분리해야 환불, 취소, 결제 실패를 안전하게 처리할 수 있다. payment_events는 웹훅 이벤트를 중복 처리하지 않기 위한 기록이다.
예를 들어 1회 분석권 결제가 성공하면 payments.status를 paid로 바꾸고, entitlements에 analysis_credit 1개를 만든다. 사용자가 리포트 생성을 요청하면 이 권한을 하나 차감하고 analysis_job을 생성한다. 환불이 발생하면 사용하지 않은 권한은 revoked로 바꾼다. 이미 리포트가 생성된 경우에는 리포트 접근을 유지할지, 공유 링크만 비활성화할지 운영 정책을 정해야 한다.
구독은 조금 다르다. 구독 결제에 성공하면 해당 기간 동안 분석 가능 횟수를 부여한다. 다음 달 결제가 실패하면 즉시 모든 기능을 막기보다 유예 기간을 둘 수 있다. 예를 들어 3일 동안은 기존 리포트 열람만 허용하고 새 분석은 막는다. 고객 경험과 비용 통제 사이의 균형이다.
웹훅은 결제 시스템의 진짜 연결점이다
결제 버튼을 누른 뒤 흐름은 보통 이렇게 진행된다.
Next.js 서버에서 결제 요청 정보를 만든다.
사용자를 결제창으로 보낸다.
사용자가 결제를 완료한다.
결제사는 성공 또는 실패 URL로 사용자를 돌려보낸다.
서버가 결제 승인 또는 상태 조회를 한다.
결제사가 웹훅으로 결제 상태 변경을 알려준다.
서버가
payments,entitlements,subscriptions를 갱신한다.
여기서 핵심은 5번과 6번을 모두 서버 기준으로 처리하는 것이다. 카드 결제처럼 즉시 승인되는 결제는 성공 URL 이후 서버 승인만으로도 빠르게 처리할 수 있다. 하지만 가상계좌 입금 완료, 환불, 부분 환불, 구독 취소처럼 시간이 지나서 바뀌는 상태는 웹훅으로 계속 동기화해야 한다. Stripe와 Lemon Squeezy 같은 글로벌 결제 도구도 이벤트 객체와 웹훅을 통해 결제 상태를 서버에서 처리하는 구조를 쓴다3.
Next.js에서는 /api/webhooks/payment 같은 Route Handler를 만든다. 이 API는 다음 원칙을 지킨다.
결제사가 제공하는 서명 검증 또는 검증 절차를 적용한다.
서명만으로 판단하기 애매한 경우 결제 조회 API로 실제 상태를 다시 확인한다.
같은 이벤트가 두 번 와도 한 번만 처리한다.
결제 금액, 상품 ID, 사용자 ID를 서버 기록과 대조한다.
성공 페이지 표시와 권한 부여를 분리한다.
처리 실패 시 로그를 남기고 재시도할 수 있게 한다.
웹훅은 중복 호출될 수 있다. TossPayments도 웹훅 수신 서버가 정상 응답을 주지 않으면 재전송을 시도하고, Stripe 역시 웹훅 이벤트를 비동기로 보내는 구조를 사용한다13. 그래서 provider_event_id를 저장해 이미 처리한 이벤트인지 확인한다. 이것을 멱등성이라고 한다. 같은 요청이 여러 번 와도 결과가 한 번 처리된 것과 같게 만드는 방식이다.
가격표 문구도 실험 대상이다
가격 실험은 금액만 바꾸는 일이 아니다. 같은 39,000원이라도 문구에 따라 전환율이 달라진다.
나쁜 가격표는 기능을 나열한다.
AI 리뷰 분석 1회
- 리뷰 100개
- PDF
- 공유 링크
- 마케팅 문구더 나은 가격표는 고객이 얻는 결과를 말한다.
리뷰 100개에서 이번 주 고칠 문제와 홍보 문구를 뽑아드립니다
- 반복 불만 TOP 5
- 바로 실행할 개선 액션 3개
- 사장님 답글 초안 10개
- 인스타그램·네이버 플레이스 홍보 문구 5개가격표는 코드보다 자주 바뀌어야 한다. 그래서 가격 문구, 제공량, CTA 문장은 데이터베이스나 설정 파일에서 관리하는 편이 좋다. 처음에는 관리자 페이지를 만들지 않아도 된다. pricing-config.ts 파일 하나로 시작해도 충분하다.
실험은 표로 남긴다.
| 기간 | 대상 | 가격 | 제한 | 핵심 문구 | 방문자 | 결제 시작 | 결제 완료 | 메모 |
|---|---|---|---|---|---|---|---|---|
| 1주차 | 카페 | 39,000원 | 리뷰 100개 | 이번 주 고칠 문제 3개 | 120 | 9 | 2 | 샘플 리포트 클릭률 높음 |
| 2주차 | 음식점 | 29,000원 | 리뷰 50개 | 악성 리뷰보다 반복 불만 찾기 | 100 | 11 | 3 | 가격 질문 감소 |
| 3주차 | 카페 | 49,000원 | 리뷰 150개 | 답글·홍보 문구 포함 | 90 | 5 | 2 | 결과물 설명 필요 |
처음부터 통계적으로 완벽한 실험을 하려 하지 않는다. 방문자가 적을 때는 숫자보다 대화가 더 중요하다. 결제하지 않은 고객에게 물어본다.
가격이 부담스러웠나요, 결과를 믿기 어려웠나요?
월 구독보다 1회 분석이 편한가요?
리뷰 몇 개까지 분석되면 충분하다고 느끼나요?
리포트에서 가장 돈 낼 만한 부분은 무엇인가요?
이 답이 다음 가격표를 만든다.
무료 사용은 비용 한도를 정한 뒤 제공한다
무료 체험은 전환율을 높일 수 있지만 AI SaaS에서는 비용이 발생한다. 리뷰 분석은 AI API 호출 비용이 있고, 리포트 저장과 파일 업로드 비용도 있다. 따라서 무료 사용은 반드시 제한이 있어야 한다.
예제 서비스에서는 다음 중 하나를 선택한다.
가입자 모두에게 데모 리포트만 제공한다.
첫 매장에 한해 리뷰 20개까지 무료 분석한다.
대기자 명단 고객에게만 1회 무료 쿠폰을 제공한다.
인터뷰에 응한 고객에게 무료 분석권을 제공한다.
가장 안전한 방식은 데모 리포트와 제한된 무료 분석을 분리하는 것이다. 데모 리포트는 비용이 거의 들지 않는다. 실제 AI 분석은 리뷰 20개까지로 제한하거나, 운영자가 승인한 고객에게만 열어준다.
무료 사용권도 entitlements에 저장한다. 결제한 권한과 무료 권한을 같은 구조로 관리하면 나중에 쿠폰, 프로모션, 환불 처리가 쉬워진다.
무료 분석권 예시
- type: analysis_credit
- source_type: coupon
- remaining_count: 1
- review_limit: 20
- starts_at: 발급 시점
- ends_at: 가입 후 14일무료 권한에는 만료일을 둔다. 만료일이 없으면 사용자는 지금 행동할 이유가 줄어든다. 14일 정도면 서비스를 살펴보고 첫 리뷰를 올리기에 충분하면서도 행동을 미루지 않게 만든다.
이번 장에서 구현할 최소 결제 범위
첫 결제 버전의 범위는 작게 잡는다.
반드시 만든다.
가격표 섹션
1회 분석권 결제 버튼
결제 대기
payments생성결제 성공 확인
웹훅 수신 API
분석권
entitlements부여분석 요청 시 권한 차감
결제 실패와 환불 상태 반영
나중으로 미룬다.
팀 결제
좌석당 과금
복잡한 쿠폰 시스템
관리자용 정산 대시보드
자동 세금계산서 발행 전체 자동화
사용량 기반 초과 과금
이렇게 줄여도 제품은 충분히 유료 실험을 시작할 수 있다. 고객은 가격표를 보고 결제하고, 우리는 결제 상태에 따라 리포트 생성 권한을 열어준다. 그 과정에서 전환율, 결제 실패율, 환불 이유, 가격 저항을 기록한다.
결제를 붙인 뒤부터는 기능 개발보다 중요한 질문이 생긴다.
'어떤 고객이, 어떤 문구를 보고, 어떤 가격에서 결제했는가?'
이 질문에 답하기 시작하면 프로젝트는 더 이상 개인 포트폴리오가 아니다. 작지만 실제 매출과 학습이 쌓이는 제품이 된다.
참고
1TossPayments 개발자센터, Webhooks, TossPayments 개발자센터, Payment APIs
2Lemon Squeezy Docs, Merchant of Record
3Stripe Documentation, Webhooks, Lemon Squeezy Docs, Webhooks
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.