OPEN HYPER STEP
← 목록으로 (master-project)
MASTER-PROJECT · 48 / 50
master-project
CHAPTER 48 / 50
읽기 약 2
FUNCTION

MRR 추적 + 성장 대시보드


핵심 개념

MRR·ARR·Churn·LTV·CAC·Cohort retention — SaaS 핵심 지표 자동 대시보드.

본문

SaaS 핵심 지표

📋 코드 (8줄)
MRR    Monthly Recurring Revenue (월 반복 수익)
ARR    Annual Recurring Revenue (= MRR × 12)
Churn  월 이탈률 (Pro → Free / 해지)
NRR    Net Revenue Retention (확장 - 이탈)
LTV    Lifetime Value (LTV = ARPU / Churn)
CAC    Customer Acquisition Cost
LTV/CAC = 3+ (건강한 SaaS)
ARPU   Average Revenue Per User

MRR 계산 (실시간)

SQL📋 코드 (8줄)
create or replace view mrr_summary as
select
  count(*) filter (where plan = 'pro') as pro_count,
  count(*) filter (where plan = 'team') as team_count,
  (count(*) filter (where plan = 'pro') * 19) +
  (count(*) filter (where plan = 'team') * 49) as mrr_dollars
from subscriptions
where status = 'active';

일별 MRR 스냅샷

SQL📋 코드 (18줄)
create table mrr_snapshots (
  date date primary key,
  mrr int not null,
  arr int generated always as (mrr * 12) stored,
  active_subs int,
  new_subs int,
  churned_subs int,
  expansion_mrr int,
  contraction_mrr int
);

-- 매일 자정 cron
insert into mrr_snapshots (date, mrr, active_subs)
select current_date, mrr_dollars, pro_count + team_count
from mrr_summary
on conflict (date) do update set
  mrr = excluded.mrr,
  active_subs = excluded.active_subs;

Churn 계산

SQL📋 코드 (8줄)
-- 월 Churn Rate
with monthly as (
  select
    date_trunc('month', current_date) as month,
    (select count(*) from subscriptions where status = 'active' and current_period_start < date_trunc('month', current_date)) as start_count,
    (select count(*) from subscriptions where status = 'canceled' and updated_at >= date_trunc('month', current_date)) as churned
)
select churned::float / nullif(start_count, 0) * 100 as churn_pct from monthly;

LTV 계산

TS📋 코드 (6줄)
// LTV = ARPU / Monthly Churn
const arpu = mrr / activeSubscriptions
const churnRate = churnedSubs / activeSubsAtStart  // 0.05 = 5%
const ltv = arpu / churnRate

// 예: ARPU $25, Churn 5% → LTV $500

CAC 계산

TS📋 코드 (6줄)
// CAC = (마케팅 + 영업 비용) / 신규 유료 사용자
const monthlyMarketing = 500  // PH·광고·콘텐츠
const newPaidUsers = 50
const cac = monthlyMarketing / newPaidUsers  // $10

// LTV/CAC = $500 / $10 = 50 (매우 좋음, 보통 3+)

Cohort Retention

SQL📋 코드 (17줄)
-- 가입 월별 retention
select
  date_trunc('month', u.created_at) as cohort,
  count(distinct u.id) as cohort_size,
  count(distinct u.id) filter (where exists(
    select 1 from generations g
    where g.user_id = u.id
    and g.created_at >= now() - interval '7 days'
  )) as active_d7,
  count(distinct u.id) filter (where exists(
    select 1 from generations g
    where g.user_id = u.id
    and g.created_at >= now() - interval '30 days'
  )) as active_d30
from users u
group by 1
order by 1 desc;

대시보드 (관리자)

TSX📋 코드 (29줄)
// src/app/admin/page.tsx
import { createServiceClient } from '@/lib/supabase/service'

export default async function AdminPage() {
  const supabase = createServiceClient()

  const { data: mrr } = await supabase.from('mrr_summary').select().single()
  const { data: snapshots } = await supabase
    .from('mrr_snapshots')
    .select()
    .gte('date', new Date(Date.now() - 90 * 86400e3).toISOString().split('T')[0])
    .order('date')

  return (
    <div className="p-6">
      <h1 className="text-2xl font-bold">MRR Dashboard</h1>

      <div className="grid grid-cols-4 gap-4 mt-6">
        <Stat label="MRR" value={`$${mrr.mrr_dollars}`} />
        <Stat label="ARR" value={`$${mrr.mrr_dollars * 12}`} />
        <Stat label="Active" value={mrr.pro_count + mrr.team_count} />
        <Stat label="Pro" value={mrr.pro_count} />
      </div>

      <MRRChart data={snapshots} />
      <CohortTable />
    </div>
  )
}

알림 (Slack)

TS📋 코드 (21줄)
// 매일 자정 → Slack 보고
async function dailyReport() {
  const today = new Date().toISOString().split('T')[0]
  const supabase = createServiceClient()

  const { data: snapshot } = await supabase
    .from('mrr_snapshots')
    .select()
    .eq('date', today)
    .single()

  await fetch(process.env.SLACK_WEBHOOK!, {
    method: 'POST',
    body: JSON.stringify({
      text: `📊 일일 MRR 보고
MRR: $${snapshot.mrr}
신규: ${snapshot.new_subs}
이탈: ${snapshot.churned_subs}`,
    }),
  })
}

목표 단계

📋 코드 (11줄)
[Month 1-3] $0~500 MRR
- 검증·MVP
- D30 retention 30%+

[Month 4-12] $500~5K MRR
- PMF 확인
- Churn < 5%/mo

[Month 13-24] $5K~50K MRR
- 가격 인상·B2B
- Net Revenue Retention 100%+

다음 챕터

CH.49 "코드 리뷰: 전체 프로젝트 최종 점검".


AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude

무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6

내 마스터 프로젝트의 MRR 대시보드 부분을 분석해서
실전 적용 + 개선 우선순위 3가지를 알려줘.
ChatGPT

무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro

MRR 대시보드 관련 모범 사례·안티패턴 5개를
비교 분석해서 실전 적용를 위한 추천 방안을 알려줘.
Gemini

무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro

내 프로젝트 전체에서 MRR 대시보드
최적화 가능 위치와 리스크를 보고해줘.
Grok

무료: Grok 4.1 / SuperGrok $30/mo

2026년 한국 1인 개발자 시장의
MRR 대시보드 트렌드와 차별화 포인트를 정리해줘.

⭐ 이것만 기억하세요
MRR 추적 + 성장 대시보드 이 3가지만 확실히 잡으세요
1.MRR + Churn + LTV + CAC = SaaS 핵심 4지표
2.Cohort retention = D7/D30 정량 측정
3.다음 챕터에서 코드 리뷰


공유하기
진행도 48 / 50