메인 콘텐츠로 건너뛰기
좌석 기반 청구는 고객이 필요한 사용자, 팀원 또는 라이센스 수에 따라 요금을 부과할 수 있게 해줍니다. 이는 팀 협업 도구, 기업 소프트웨어 및 B2B SaaS 제품의 표준 가격 모델입니다.

좌석 기반 청구란?

좌석 기반 청구(사용자별 또는 좌석별 가격 책정이라고도 함)는 고객이 제품에 접근하는 사용자 수에 따라 요금을 부과합니다. 고정 요금 대신 팀 규모에 따라 가격이 조정됩니다.

일반적인 사용 사례

산업예시가격 모델
팀 협업Slack, Notion, Asana활성 사용자 기준/월
개발 도구GitHub, GitLab, Jira좌석 기준/월
CRM 소프트웨어Salesforce, HubSpot사용자 라이센스 기준
디자인 도구Figma, Canva편집자 좌석 기준
보안 소프트웨어1Password, Okta사용자 기준/월
화상 회의Zoom, Teams호스트 라이센스 기준

좌석 기반 가격 책정의 이점

귀하의 비즈니스를 위해:
  • 고객이 성장함에 따라 수익이 자연스럽게 증가
  • 고객이 예산을 세울 수 있는 예측 가능한 가격
  • 개인에서 팀, 기업으로의 명확한 업그레이드 경로
  • 팀이 확장됨에 따라 더 높은 고객 생애 가치
고객을 위해:
  • 사용하는 만큼만 지불
  • 비용을 이해하고 예측하기 쉬움
  • 필요에 따라 사용자 추가/제거의 유연성
  • 팀 규모에 맞는 공정한 가격

Dodo Payments에서의 좌석 기반 청구 작동 방식

Dodo Payments는 부가 기능 시스템을 사용하여 좌석 기반 청구를 구현합니다. 작동 방식은 다음과 같습니다:

아키텍처 개요

팀 프로 구독은 $99/월이며 5개의 좌석이 포함됩니다. 5명 이상의 사용자가 있는 경우 추가 좌석마다 $15/월을 지불합니다. 예를 들어, 팀에 15개의 좌석이 필요한 경우:
  • 기본 요금제: $99/월 (5개 좌석 포함)
  • 부가 기능: 10개의 추가 좌석 × $15/월 = $150/월
  • 총 월 비용: $99 + $150 = $249 (15개 좌석)

주요 구성 요소

구성 요소목적예시
기본 제품포함된 좌석이 있는 핵심 구독”팀 요금제 - $99/월 (5개 좌석 포함)“
좌석 부가 기능추가 사용자에 대한 좌석 요금”추가 좌석 - $15/월”
수량구매한 추가 좌석 수10개 추가 좌석

가격 책정 전략

비즈니스에 맞는 좌석 기반 가격 책정 전략을 선택하세요:

전략 1: 기본 + 좌석별 부가 기능

기본 요금제에 정해진 수의 좌석을 포함하고 추가 좌석에 대해 요금을 부과합니다. 예시:
Starter Plan: $49/month
├── Includes: 3 seats
├── Extra seats: $10/month each
└── 8 total seats = $49 + (5 × $10) = $99/month
최고의 경우: 소규모 팀이 기본 제공으로 기능할 수 있는 제품.

전략 2: 순수 좌석별 가격 책정

기본 요금 없이 좌석당 고정 요금을 부과합니다. 예시:
Per User: $12/month
├── 5 users = $60/month
├── 20 users = $240/month
└── 100 users = $1,200/month
구현: 기본 요금제를 $0으로 설정하고 좌석 부가 기능만 사용합니다. 최고의 경우: 간단하고 투명한 가격 책정; 사용량 기반 모델.

전략 3: 계층형 좌석 가격 책정

다양한 기본 요금제와 서로 다른 좌석당 요금. 예시:
Starter: $0/month base + $15/seat
├── Lower features, higher per-seat cost

Professional: $99/month base + $10/seat
├── More features, lower per-seat cost

Enterprise: $499/month base + $7/seat
└── All features, volume discount on seats
구현: 각 계층에 대해 서로 다른 부가 기능 가격으로 별도의 제품을 만듭니다. 최고의 경우: 더 높은 계층으로의 업그레이드를 장려; 기업 판매.

전략 4: 좌석 번들

좌석을 개별적으로 판매하는 대신 묶음으로 판매합니다. 예시:
5-Seat Pack: $50/month ($10/seat)
10-Seat Pack: $80/month ($8/seat)
25-Seat Pack: $175/month ($7/seat)
구현: 다양한 묶음 크기에 대해 여러 부가 기능을 만듭니다. 최고의 경우: 구매 결정을 단순화; 더 큰 약속을 장려합니다.

좌석 기반 청구 설정하기

1단계: 가격 책정 계획하기

구현 전에 가격 구조를 정의합니다:
1

기본 요금제 정의

기본 구독에 포함된 내용을 결정합니다:
  • 기본 가격 (순수 좌석 기준의 경우 $0일 수 있음)
  • 포함된 좌석 수
  • 이 계층에서 사용할 수 있는 기능
2

좌석 가격 설정

좌석당 부가 기능 비용을 결정합니다:
  • 추가 좌석당 가격
  • 대량 할인 (여러 부가 기능을 통해)
  • 허용되는 최대 좌석 수 (해당되는 경우)
3

청구 주기 고려하기

좌석 가격을 청구 주기와 일치시킵니다:
  • 월간 구독 → 월간 좌석 요금
  • 연간 구독 → 연간 좌석 요금 (종종 할인됨)

2단계: 좌석 부가 기능 만들기

Dodo Payments 대시보드에서:
  1. 제품부가 기능으로 이동합니다.
  2. 부가 기능 만들기를 클릭합니다.
  3. 부가 기능을 구성합니다:
필드비고
이름”추가 좌석” 또는 “팀원”명확하고 사용자 친화적인 이름
설명”작업 공간에 팀원을 추가하세요”고객이 얻는 것 설명
가격좌석당 가격예: $10.00
통화기본 제품과 일치반드시 동일한 통화여야 함
세금 카테고리기본 제품과 동일일관된 세금 처리를 보장
청구서에서 이해하기 쉬운 설명적인 부가 기능 이름을 만드세요. “추가 팀 좌석”은 고객이 청구서를 검토할 때 “좌석 부가 기능”보다 더 명확합니다.

3단계: 기본 구독 만들기

구독 제품을 만듭니다:
  1. 제품제품 만들기로 이동합니다.
  2. 구독 선택
  3. 가격 및 세부정보 구성
  4. 부가 기능 섹션에서 좌석 부가 기능을 연결합니다.

4단계: 제품에 부가 기능 연결하기

좌석 부가 기능을 구독에 연결합니다:
  1. 구독 제품을 편집합니다.
  2. 부가 기능 섹션으로 스크롤합니다.
  3. 부가 기능 추가 클릭
  4. 좌석 부가 기능 선택
  5. 변경 사항 저장
귀하의 구독 제품은 이제 좌석 기반 가격 책정을 지원합니다. 고객은 체크아웃 중에 추가 좌석을 원하는 만큼 구매할 수 있습니다.

좌석 관리

새로운 구독에 좌석 추가하기

체크아웃 세션을 생성할 때 좌석 수를 지정합니다:
const session = await client.checkoutSessions.create({
  product_cart: [{
    product_id: 'prod_team_plan',
    quantity: 1,
    addons: [{
      addon_id: 'addon_seat',
      quantity: 10  // 10 additional seats
    }]
  }],
  customer: { email: '[email protected]' },
  return_url: 'https://yourapp.com/success'
});

기존 구독의 좌석 수 변경하기

좌석을 조정하려면 Change Plan API를 사용합니다:
// Add 5 more seats to existing subscription
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_team_plan',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately',
  addons: [{
    addon_id: 'addon_seat',
    quantity: 15  // New total: 15 additional seats
  }]
});

좌석 제거하기

좌석 수를 줄이려면 더 낮은 수량을 지정합니다:
// Reduce from 15 to 8 additional seats
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_team_plan',
  quantity: 1,
  proration_billing_mode: 'difference_immediately',
  addons: [{
    addon_id: 'addon_seat',
    quantity: 8  // Reduced to 8 additional seats
  }]
});

모든 추가 좌석 제거하기

모든 부가 기능을 제거하려면 빈 addons 배열을 전달합니다:
// Remove all additional seats, keep only base plan seats
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_team_plan',
  quantity: 1,
  proration_billing_mode: 'difference_immediately',
  addons: []  // Removes all add-ons
});

좌석 변경에 대한 비례 배분

고객이 중간 주기에 좌석을 추가하거나 제거할 때 비례 배분이 청구 방식을 결정합니다.

비례 배분 모드

모드좌석 추가좌석 제거
prorated_immediately주기 내 남은 일수에 대해 요금 부과사용하지 않은 일수에 대해 크레딧
difference_immediately전체 좌석 가격 부과향후 갱신에 적용되는 크레딧
full_immediately전체 좌석 가격 부과, 청구 주기 재설정크레딧 없음

비례 배분 예시

시나리오: 남은 15일 청구 주기, 좌석당 $10에 5개 좌석 추가
Prorated charge = ($10 × 5 seats) × (15 days / 30 days)
                = $50 × 0.5
                = $25 immediate charge
고객은 지금 $25를 지불하고, 갱신 시 $50/월을 지불합니다.

변경 전 미리보기

변경하기 전에 항상 비례 배분을 미리 봅니다:
const preview = await client.subscriptions.previewChangePlan('sub_123', {
  product_id: 'prod_team_plan',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately',
  addons: [{ addon_id: 'addon_seat', quantity: 20 }]
});

console.log('Immediate charge:', preview.immediate_charge.summary);
// Show customer: "Adding 5 seats will cost $25 today"

웹훅으로 좌석 추적하기

구독 웹훅을 수신하여 좌석 변경 사항을 모니터링합니다:

관련 이벤트

이벤트트리거 시점사용 사례
subscription.active새로운 구독 활성화초기 좌석 프로비저닝
subscription.plan_changed좌석 추가/제거앱에서 좌석 수 업데이트
subscription.renewed구독 갱신좌석 수가 변경되지 않았는지 확인
subscription.cancelled구독 취소모든 좌석 비활성화

웹훅 핸들러 예시

app.post('/webhooks/dodo', async (req, res) => {
  const event = req.body;

  switch (event.type) {
    case 'subscription.active':
      // New subscription - provision seats
      const seats = calculateTotalSeats(event.data);
      await provisionSeats(event.data.customer_id, seats);
      break;

    case 'subscription.plan_changed':
      // Seats changed - update access
      const newSeats = calculateTotalSeats(event.data);
      await updateSeatCount(event.data.subscription_id, newSeats);
      break;

    case 'subscription.cancelled':
      // Subscription cancelled - deprovision
      await deprovisionAllSeats(event.data.subscription_id);
      break;
  }

  res.json({ received: true });
});

function calculateTotalSeats(subscriptionData) {
  const baseSeats = 5;  // Included in plan
  const addonSeats = subscriptionData.addons?.reduce(
    (total, addon) => total + addon.quantity, 0
  ) || 0;
  return baseSeats + addonSeats;
}

좌석 한도 강제 적용

귀하의 애플리케이션은 좌석 한도를 강제 적용해야 합니다. Dodo Payments는 청구를 추적하지만, 귀하가 접근을 제어합니다.

강제 적용 전략

좌석 수를 초과하여 사용자를 추가하는 것을 엄격히 방지합니다.
async function inviteUser(teamId: string, email: string) {
  const team = await getTeam(teamId);
  const subscription = await getSubscription(team.subscriptionId);
  const totalSeats = calculateTotalSeats(subscription);
  const usedSeats = await countTeamMembers(teamId);

  if (usedSeats >= totalSeats) {
    throw new Error('No seats available. Please upgrade your plan.');
  }

  await sendInvitation(teamId, email);
}

고급 패턴

다양한 좌석 유형

다양한 가격으로 다양한 좌석 유형을 제공합니다:
Full Seats: $20/month - Full access to all features
View-Only Seats: $5/month - Read-only access
Guest Seats: $0/month - Limited external collaborator access
구현: 각 좌석 유형에 대해 별도의 부가 기능을 만듭니다.
const session = await client.checkoutSessions.create({
  product_cart: [{
    product_id: 'prod_team_plan',
    quantity: 1,
    addons: [
      { addon_id: 'addon_full_seat', quantity: 10 },
      { addon_id: 'addon_viewer_seat', quantity: 25 },
      { addon_id: 'addon_guest_seat', quantity: 50 }
    ]
  }]
});

연간 좌석 할인

할인된 연간 좌석 가격을 제공합니다:
Monthly: $15/seat/month
Annual: $12/seat/month (20% savings)
구현: 월간 및 연간 요금제에 대해 서로 다른 부가 기능 가격으로 별도의 제품을 만듭니다.

최소 좌석 요구 사항

특정 요금제에 대해 최소 좌석 수를 요구합니다:
async function validateSeatCount(planId: string, seatCount: number) {
  const minimums = {
    'prod_starter': 1,
    'prod_team': 5,
    'prod_enterprise': 25
  };

  if (seatCount < minimums[planId]) {
    throw new Error(`${planId} requires at least ${minimums[planId]} seats`);
  }
}

모범 사례

가격 책정 모범 사례

  • 명확한 커뮤니케이션: 가격 페이지에 좌석당 가격을 눈에 띄게 표시
  • 포함된 좌석: 마찰을 줄이기 위해 기본 가격에 몇 개의 좌석을 포함하는 것을 고려
  • 대량 할인: 더 큰 팀을 위해 낮은 좌석당 요금을 제공하여 기업 거래를 유치
  • 연간 인센티브: 연간 요금제를 할인하여 현금 흐름 및 유지율 개선

기술 모범 사례

  • 좌석 수 캐시: API 호출을 피하기 위해 구독 좌석 수를 로컬에 캐시
  • 정기적으로 동기화: API를 통해 Dodo Payments와 로컬 좌석 수를 주기적으로 동기화
  • 실패 처리: 좌석 변경이 실패할 경우 명확한 오류 메시지 및 재시도 옵션 표시
  • 감사 추적: 청구 분쟁 및 준수를 위해 모든 좌석 변경 사항을 기록

사용자 경험 모범 사례

  • 실시간 피드백: 좌석 조정 시 즉각적인 비용 영향을 보여줍니다.
  • 확인 단계: 청구 변경 전에 확인을 요구합니다.
  • 비례 배분 투명성: 적용하기 전에 비례 배분 요금을 명확히 설명합니다.
  • 쉬운 다운그레이드: 좌석을 줄이는 것을 어렵게 만들지 마세요 (신뢰를 구축합니다).

문제 해결

증상: 귀하의 앱이 구독과 다른 좌석 수를 표시합니다.원인:
  • 웹훅이 수신되지 않거나 처리되지 않음
  • 좌석 변경 중 경쟁 조건
  • 캐시된 데이터가 업데이트되지 않음
해결책:
  1. subscription.plan_changed에 대한 웹훅 핸들러를 구현합니다.
  2. 현재 구독을 가져오는 “청구와 동기화” 버튼 추가
  3. 정기적인 새로 고침을 보장하기 위해 캐시 TTL 설정
증상: 고객이 중간 주기 요금에 혼란스러워합니다.원인:
  • 비례 배분 모드가 명확하게 전달되지 않음
  • 고객이 확인하기 전에 미리보기를 보지 않음
해결책:
  1. 변경하기 전에 항상 previewChangePlan를 사용하세요.
  2. 명확한 세부 내역 표시: “X 좌석 추가 = 오늘 $Y (Z일 비례 배분)”
  3. 도움말 센터에 비례 배분 정책 문서화
증상: 체크아웃 중 좌석 부가 기능이 사용 가능하지 않음.원인:
  • 제품에 부가 기능이 연결되지 않음
  • 부가 기능이 보관되었거나 삭제됨
  • 제품과 부가 기능 간의 통화 불일치
해결책:
  1. 제품 설정에서 부가 기능이 연결되어 있는지 확인
  2. 부가 기능 대시보드에서 부가 기능 상태 확인
  3. 통화가 정확히 일치하는지 확인
증상: 고객이 좌석을 줄이기를 원하지만 사용자가 할당되어 있음.해결책:
  1. 좌석을 줄이기 전에 제거해야 할 사용자를 보여줍니다.
  2. 워크플로우 구현: 사용자 제거 → 좌석 줄이기
  3. 좌석 감소를 시행하기 전에 유예 기간을 고려합니다.

관련 문서