귀찮은개발자16 min

ASC 대시보드가 생겼는데 뭘 해야 할지 몰라서 AI한테 맡겼다

Apsity 대시보드로 앱 12개 수익은 보이는데, 그래서 뭘 해야 할지는 여전히 몰랐다. AI 그로스 에이전트를 만들었다. 48개 인사이트가 자동



 

2026년 3월 · 귀찮은개발자 EP.03

대시보드가 생겼다. EP.02에서 만든 거다. 매일 새벽 3시에 Cron이 돌고, 아침에 일어나면 앱 12개의 어제 데이터가 전부 들어와 있다. 다운로드 합산, 매출, 키워드 순위. 한 화면에 다 나온다. 이걸 만드는 데 며칠이 걸렸고, 매일 아침 15분이 생겼다.

근데 3일쯤 지나서 다른 종류의 질문이 남았다. “가계부 앱 다운로드가 오늘 22% 내려갔네.” 화면에 숫자가 있다. 그래서? 왜 내려갔는지는 모른다. 뭘 해야 하는지도 모른다. 대시보드는 현상을 보여주고, 판단은 여전히 내가 해야 한다. 대시보드가 생겼더니 판단해야 할 것들이 더 명확하게 보여서, 어떻게 보면 더 피곤해졌다.

그래서 판단하는 것도 자동화하기로 했다. Apsity 안에 AI 그로스 에이전트를 넣었다. 이번 글은 그 얘기다.

빠르게 보기

– 대시보드는 “현상”을 보여주지만, “왜, 뭘 해야 하는지”는 여전히 내가 판단해야 했다
– 5가지 분석 패턴 설계: 순위 하락 진단, 숨은 시장, 키워드 최적화, 리뷰 분석, 매출 분해
– 모든 인사이트에 신뢰도 뱃지 부착: 팩트 / 상관관계 / 제안 구분
– 인디앱 필터로 대기업 앱(평점 1,000+) 제외, 실제 비교 가능한 앱만 분석
– Claude API 두 번째 연결 — 키워드 100자 세트 자동 생성, App 이름 제안, 인사이트 추출
– 성장 단계 자동 판정: 🌱SEED → 🌿GROWING → 🌳STABLE
– 주간 메일 리포트 추가: 월요일 아침 8시, Resend + React Email로 자동 발송
– 첫 실행에서 12개 앱, 48개 인사이트 자동 생성

기존 도구들이 말해주지 않는 것 — 그리고 가격

App Store 관련 분석 도구들은 꽤 많다. AppFollow, Sensor Tower, MobileAction, 거기에 App Store Connect 자체도 있다. 근데 이것들이 공통으로 하는 일이 있다. “이번 주 다운로드 3,240개입니다.” “키워드 순위 변동 -5.” 다 현상을 숫자로 보여준다.

가격을 먼저 보면 얘기가 정리된다. Sensor Tower 엔터프라이즈 플랜은 연 $30,000부터 시작한다. 협상하면 좀 내려가기도 하지만 인디 개발자가 쓸 수 있는 가격이 아니다. AppFollow는 월 $39짜리 기본 플랜이 있는데, 앱 5개 제한이다. 12개를 관리하려면 플랜이 올라가고 비용도 뛴다. 그래서 많은 인디 개발자들이 App Store Connect(ASC) 자체 분석 기능을 쓴다.

ASC 자체도 문제가 있다. 2026년 1월에는 IAP 매출이 갑자기 0으로 표기되는 버그가 발생했다. 실제 매출이 들어오고 있는데 화면에는 0이 찍혔다. 2026년 3월 업데이트로 100개 이상의 새 지표가 생겼지만, 앱 여러 개를 한 화면에서 합산해서 보는 기능은 여전히 없다. 앱이 12개면 12번 들어가야 한다. EP.02에서 대시보드를 직접 만든 이유가 이거였다.

이 숫자들을 보면서 “그래서?”라는 질문이 남는 건 어떤 도구를 쓰든 마찬가지다. 왜 내려갔는지, 경쟁앱이 뭔가 바꾼 건지, 내 키워드가 문제인지, 리뷰에서 뭔가 신호가 나오는 건지. 이걸 알아내려면 데이터를 직접 파야 한다. 도구들은 삽을 들어주지 않는다.

내가 원하는 건 달랐다. 데이터를 주면 원인을 말해주고, 원인이 있으면 뭘 해야 하는지를 알려주고, 뭘 해야 하는지 알면 지금 바로 쓸 수 있는 결과물을 내줬으면 했다. “키워드를 이렇게 바꾸는 게 좋겠어요”가 아니라 “이 100자를 App Store 키워드 필드에 복사하세요”처럼.

AI 그로스 에이전트 — 판단을 대신하는 구조

Claude에 요구사항을 정리해서 던졌다. “현상만 보여주는 게 아니라 원인 진단, 검증 가능한 근거, 바로 쓸 수 있는 결과물을 주는 분석 기능.” 한 줄짜리 설명이었는데, Claude가 5가지 분석 패턴으로 쪼개줬다.

// 5가지 분석 패턴
1. 순위 하락 진단 — 왜 내려갔는지, 경쟁앱 변화 포함
2. 숨은 시장 발견 — 내 앱이 노출 안 되는 키워드 중 기회가 있는 것
3. 키워드 최적화 — 현재 키워드 분석 + 100자 최적 세트 자동 생성
4. 리뷰 키워드 분석 — 사용자 리뷰에서 반복되는 패턴 추출
5. 매출 분해 — 구독 vs IAP 이상치 감지 + 원인 가설

패턴만 있으면 의미가 없다. 각 분석 결과가 얼마나 믿을 수 있는지가 중요하다. AI가 하는 말이라고 다 팩트가 아니고, 데이터에서 직접 읽어온 것과 패턴으로 추론한 것, AI가 제안하는 것은 성격이 다르다. 그걸 구분하지 않으면 추론을 팩트처럼 받아들이게 된다.

신뢰도 뱃지를 넣은 이유

모든 인사이트 카드에 신뢰도 뱃지를 붙였다. 세 가지다.

팩트
실제 데이터에서 직접 확인된 것. “어제 다운로드 22% 하락”처럼 수치로 측정된 사실.
상관관계
데이터 간 패턴에서 유추된 것. “경쟁앱 설명 변경 직후 순위 변동”처럼 연관성은 있지만 인과가 확인된 건 아닌 것.
제안
분석 기반 AI 추론. “이 키워드를 추가하면 노출이 늘 수 있어요”처럼 데이터에 기반하되 확정은 아닌 것.

각 카드에는 [근거 보기] 토글도 달았다. 눌렀을 때 “지난 7일 다운로드 평균 대비 34% 이탈, 동일 기간 경쟁앱 A가 메타데이터 3개 변경” 같은 원본 데이터가 나온다. AI가 어떤 데이터를 보고 이 인사이트를 냈는지 확인할 수 있게. 믿어도 되는지 내가 판단할 수 있게.

이건 기능 설계이기도 하지만 철학이기도 하다. AI가 말하는 것을 그냥 따르는 게 아니라, AI가 왜 그렇게 말하는지 볼 수 있어야 한다. 그래야 틀렸을 때도 알 수 있다.

인디앱 필터 — 비교 대상이 잘못되면 분석이 무용지물

경쟁앱 분석을 설계하다가 한 가지 문제가 생겼다. 같은 카테고리에 있는 앱이라도 비교하면 안 되는 앱들이 있다. 대형 금융사 공식 앱, 네이버·카카오 계열 앱들. 이런 앱들은 마케팅 예산이 다르고, ASO(앱 검색 최적화) 전략도 다르고, 평점 수도 수십만이다. 인디 개발자가 이 앱들과 같은 기준으로 비교받으면 의미 있는 인사이트가 안 나온다.

Claude한테 물었더니 평점 수 기반 필터를 제안했다. 평점 1,000개 이상인 앱은 대기업 앱으로 보고 비교 대상에서 제외한다. 평점 50~1,000개 사이인 앱은 인디 성공 앱으로 분류해서 비교 기준으로 쓴다. 생각해보면 당연한 거였는데, 설계할 때 이걸 직접 생각하려면 한참 걸렸을 거다.

인디앱 필터의 기준은 간단하다. App Store에서 앱의 평점 수(리뷰 개수)는 다운로드 수에 비례한다. 평점이 1,000개 이상이면 이미 충분한 마케팅이 들어간 앱이고, 그 앱은 인디가 아니다. 반대로 50~1,000개면 어느 정도 검증됐지만 아직 인디 규모인 앱이다. 이 범위가 진짜 비교해야 할 대상이다.

경쟁앱 메뉴 — 어제 뭔가 바꾼 앱이 있는지 매일 확인한다

인디앱 필터를 설계하고 나서 Competitors 메뉴를 만들었다. 기능 자체는 단순하다. 그런데 실제로 제일 자주 열게 됐다.

구조는 이렇다. 경쟁앱을 등록하면 Cron이 매일 새벽 4시(UTC 19:00)에 iTunes Lookup API를 호출해서 해당 앱의 최신 메타데이터를 가져온다. 앱 이름, 부제, 설명, 아이콘, 버전. 이 다섯 가지를 CompetitorSnapshot에 매일 저장하고, 전날이랑 비교해서 바뀐 게 있으면 MetaChange 테이블에 변경 이력을 쌓는다.

메뉴를 열면 등록된 경쟁앱 목록이 나온다. 최근 메타데이터 변경이 있는 앱이 상단에 올라오고, 어떤 필드가 바뀌었는지 표시된다. 변경된 필드를 클릭하면 이전 버전이랑 현재 버전을 나란히 볼 수 있다. 아이콘이 바뀌었는지, 설명 문구가 어떻게 달라졌는지까지 텍스트 diff로 확인된다.

메뉴에는 탭이 세 개다. 변경 이력 탭 외에 키워드 순위 비교 탭이 있다. 내가 추적하는 키워드에서 경쟁앱이 몇 위인지 나라별로 비교할 수 있다. 9개 국가(한국·미국·일본·영국·독일 등)를 지원한다. 리뷰 탭에서는 경쟁앱의 최신 리뷰를 바로 볼 수 있다. 경쟁사 사용자들이 뭘 불만으로 쓰는지 읽으면 내 앱 업데이트 방향이 잡히는 경우가 있다.

Competitors 메뉴 구성: 변경 이력 탭 (이름·부제·설명·아이콘·버전 diff) / 키워드 순위 비교 탭 (9개국) / 경쟁앱 리뷰 탭. Cron은 매일 새벽 4시 KST에 동작. 등록 가능한 경쟁앱 수는 플랜에 따라 다르다. FREE 3개, STARTER 10개, PRO 무제한.

처음엔 “이게 의미가 있나?” 싶었다. 경쟁앱이 설명을 바꿨다고 내가 할 수 있는 게 있는 건지. 써보니까 달랐다. 가계부 앱에서 경쟁앱 3개가 같은 날 설명과 키워드를 동시에 업데이트했고, 그 직후 내 순위가 내려갔다. MetaChange 이력에 날짜와 변경 내용이 남아 있었다. 상관관계이지 인과는 아니지만, 이 정보가 없었으면 원인을 파악하러 훨씬 오래 걸렸을 거다.

자동화의 이유가 여기서 명확해진다. 경쟁앱 수십 개를 매일 App Store에서 직접 들어가 확인하는 건 물리적으로 못 한다. 그냥 안 하게 된다. Cron이 매일 긁어오고, 변경이 있으면 30초 안에 어제 달라진 게 뭔지 파악된다. 귀찮으니까 만드는 거고, 만들고 나면 하게 된다.

Claude API를 Apsity 안에 두 번째로 넣었다 — 키워드 메뉴에서

EP.02에서도 Claude API를 Apsity에 연결했다. 앱 데이터를 주면 이번 주 뭘 집중해야 할지 짧게 제안해주는 기능이었다. 이번엔 더 구체적으로 두 가지를 추가했다. 키워드 100자 최적 세트를 자동으로 생성하는 것, 그리고 인디 성공 앱 패턴 기반으로 앱 이름과 부제를 제안하는 것이다. 두 기능 모두 Apsity의 키워드 메뉴 안에서 바로 쓸 수 있다. 별도 메뉴로 분리하지 않았다. 키워드를 관리하다가 바로 AI 제안을 받고 복사할 수 있게 붙여놨다.

// POST /api/growth/keywords-generate
// 앱 이름, 카테고리, 현재 키워드 → Claude → 100자 최적 키워드 세트

const prompt = `
앱: ${appName} (${category})
현재 키워드: ${currentKeywords}
상위 인디앱 키워드 패턴: ${indiePatterns}

App Store 키워드 필드 100자 이내로 최적화된 키워드 세트를 만들어줘.
중복 단어 제거, 공백 없이 쉼표로 구분.`

키워드 필드에는 규칙이 있다. Claude한테 이걸 먼저 알려줬다. 쉼표 뒤 공백 없이 쉼표만 (공백 하나도 글자 수 차지), 복수형 금지 (App Store가 단수에서 자동 매칭), 앱 이름과 카테고리 이름 중복 금지 (이미 별도 필드에서 잡힘), 100자 전부 채우기 (빈 자리 = 노출 기회 낭비). 리뷰에서 자주 등장하는 단어도 키워드 시그널로 작동하기 때문에, 리뷰 텍스트에서 뽑은 반복 키워드를 포함시키는 게 유리하다.

App Store 키워드 100자 규칙
✓ 쉼표 뒤 공백 없음 — 가계부,지출,절약 (공백 한 칸도 글자 수 차지)
✓ 복수형 금지 — App Store가 단수에서 자동으로 복수 매칭
✓ 앱 이름·카테고리 중복 금지 — 이미 별도 필드에서 검색에 잡힘
✓ 100자 전부 채우기 — 빈 자리는 노출 기회 낭비
✓ 리뷰 키워드 포함 — 리뷰 텍스트에 자주 나온 단어가 검색 시그널로 작동

키워드 최적화 — AI가 생성한 100자 최적 세트를 버튼 하나로 복사 / GoCodeLab

Claude가 키워드를 생성해주면, 결과 카드에 바로 복사 버튼이 뜬다. 클릭 한 번이면 App Store Connect 키워드 필드에 붙여넣을 수 있는 형태로 클립보드에 들어간다. “이렇게 바꿔보세요”가 아니라 “이걸 복사해서 붙여넣으세요”다. 조언과 결과물은 다르다.

앱 이름 제안도 비슷한 방식이다. 인디 성공 앱들의 이름 패턴을 분석하고 — 짧고, 기능이 명확하고, 검색 키워드가 포함된 — 거기서 추출한 패턴을 기반으로 현재 앱 이름의 대안을 제안한다. 쓸지 말지는 내가 판단한다. 하지만 선택지가 있는 게 없는 것보다 낫다.

성장 단계 적응형 모드 — 🌱에서 🌳까지

분석 기능을 다 만들고 나서 한 가지 문제가 보였다. 이제 막 출시한 앱한테 “매출 이상치 감지”를 돌리면 의미가 없다. 데이터가 없으니까. 반대로 안정적으로 운영 중인 앱한테 기초적인 키워드 자동 생성만 해주면 아쉽다. 앱마다 상황이 다른데, 같은 분석을 돌리면 안 된다.

Claude한테 이 문제를 설명했더니 성장 단계를 자동으로 판정하는 방식을 제안했다.

🌱
SEED — 출시 직후
다운로드 30일 미만 또는 누적 500개 미만. 키워드 자동 생성, 앱 이름 제안처럼 초기 세팅에 집중. 데이터가 없으니 패턴 분석 대신 인디 앱 성공 공식을 기반으로 함.
🌿
GROWING — 성장 중
다운로드 트렌드가 올라가고 있거나 안정적. 순위 하락 진단, 숨은 시장 발견, 경쟁앱 변화 감지가 활성화됨. 이 단계에서 가장 많은 인사이트가 나옴.
🌳
STABLE — 안정 운영
3개월 이상 데이터가 쌓인 앱. 매출 이상치 감지, 리뷰 키워드 분석, 장기 트렌드 패턴 분석이 활성화됨. 세밀한 최적화 단계.

성장 단계 자동 판정 — 🌱SEED / 🌿GROWING / 🌳STABLE, 단계마다 활성화되는 분석이 다르다 / GoCodeLab

단계 판정은 자동이다. 매일 Cron이 돌 때 각 앱의 데이터 양, 다운로드 트렌드, 운영 기간을 보고 SEED / GROWING / STABLE을 판정한다. 같은 날 같은 앱이라도 상황이 바뀌면 단계가 바뀔 수 있다. 빠르게 성장 중이던 앱이 갑자기 하락하면 GROWING에서 분석이 다시 돌아간다.

Claude가 내 코드를 리뷰했다

이번 작업에서 새로 해본 게 하나 있다. 코드 리뷰를 Claude한테 맡겼다. 만들 때는 Claude가 써줬는데, 다 만들고 나서 “이 코드 전체를 리뷰해줘, 운영 중에 문제가 생길 수 있는 것 위주로”라고 했다.

생각보다 구체적으로 나왔다. Critical과 Important로 나눠서 각 항목마다 어떤 파일 몇 번째 줄인지, 어떤 상황에서 문제가 생기는지, 어떻게 고치면 되는지를 같이 줬다. 1차 리뷰에서 Critical 3건이 나왔다.

// [Critical] 1차 리뷰 주요 항목
1. MetaChange 관계 누락 — DB 저장 시 관계 테이블 연결 안 됨
2. JSON.parse 미보호 — 외부 API 응답 파싱 시 try-catch 없음
3. Cron 타임아웃 — 12개 앱 직렬 처리 시 타임아웃 위험

// [Critical] 2차 리뷰 주요 항목
4. iTunes API rate limit — 루프 안에서 지연 없이 호출 시 429 위험
5. 리뷰 국가 하드코딩 — KR만 수집, 다국가 누락
6. ASC 데이터 지연 — 어제 데이터가 오늘 새벽에 없을 수 있음

3번 Cron 타임아웃은 EP.02에서도 만났던 문제고, after() 패턴으로 이미 해결하는 법을 알고 있었다. 여기서도 그대로 적용했다. 4번 iTunes API rate limit은 루프 안에서 요청 사이에 200ms 지연을 넣는 걸로 해결했다. 6번 ASC 데이터 지연은 재시도 로직을 추가해서, 어제 데이터가 없으면 6시간 후 다시 가져오게 했다.

이상한 감각이 있었다. Claude로 만든 코드를 Claude가 리뷰하고, Claude가 찾아낸 문제를 Claude가 고쳐준다. 어디서부터 어디까지가 내가 만든 건지 경계가 더 흐릿해졌다. 근데 운영 중에 터지는 것보다는 이 감각이 낫다.

주간 메일 리포트 — 월요일 아침 8시에 받는 요약

인사이트가 생겼는데, 대시보드를 열어야만 볼 수 있다는 게 마음에 걸렸다. 열지 않으면 놓친다. 월요일 아침을 Apsity 대시보드를 열기 전에 이미 한 주가 어땠는지 알고 시작하면 좋겠다고 생각했다. 그래서 주간 리포트를 이메일로 자동 발송하기로 했다.

스택 선택은 간단했다. Next.js API Route 안에서 이메일을 보내는 방법을 찾았고, Resend + React Email 조합이 가장 깔끔했다. React Email은 이메일 템플릿을 React 컴포넌트로 쓸 수 있게 해준다. 일반 HTML 이메일 짜다가 인라인 스타일 지옥에 빠지는 걸 피할 수 있다.

// app/api/cron/weekly-report/route.ts
export async function GET() {
  // after() — 즉시 응답 후 백그라운드에서 처리
  after(async () => {
    const summary = await weeklyDataSummary()
    const topInsights = await getTopInsights(7)
    await resend.emails.send({
      from: ‘Apsity <report@apsity.app>’,
      to: user.email,
      subject: `${weekRange} 주간 리포트`,
      react: <WeeklyReportEmail
              summary={summary}
              insights={topInsights} />
    })
  })
  return NextResponse.json({ ok: true })
}

after() 패턴을 여기서도 쓴다. EP.02에서 Cron 타임아웃 문제 때 배운 패턴이다. 이메일 발송이 느려도 응답은 즉시 나간다. Vercel 타임아웃에 걸릴 일이 없다.

발송 스케줄은 vercel.json에 추가했다. 월요일 오전 8시로 맞췄다.

// vercel.json — Cron 스케줄
{
  “crons”: [
    { “path”: “/api/cron/collect”, “schedule”: “0 18 * * *” }, // 매일 새벽 3시 KST
    { “path”: “/api/cron/analyze”, “schedule”: “30 10 * * *” }, // 매일 저녁 7:30 KST
    { “path”: “/api/cron/weekly-report”, “schedule”: “0 23 * * 0” } // 월요일 오전 8시 KST
  ]
}

메일 안에 들어가는 내용은 세 가지로 정했다. 지난 7일 앱별 다운로드·매출 요약, 이번 주 상위 3개 인사이트 (신뢰도 뱃지 포함), 그리고 즉시 실행 가능한 액션 한 가지. 길게 쓰면 안 읽게 된다는 걸 알고 있어서, 스크롤 없이 한 화면에 끝내는 걸 목표로 설계했다.

월요일 아침 8시에 메일이 온다. 열어보면 지난 주 요약이 한 화면에 들어와 있다. 가장 중요한 인사이트 하나와 “이번 주 이것만 해보세요” 액션이 마지막에 붙는다. 대시보드를 열기 전에 이미 이번 주 방향이 잡혀 있다.

주간 메일 리포트 — 월요일 오전 8시에 자동 발송, 스크롤 없이 한 화면 완결 / GoCodeLab

첫 실행 — 48개 인사이트

Cron을 배포하고 수동으로 돌렸다. 12개 앱 처리, 총 실행 시간 38초. Supabase에 rows가 들어갔다. 숫자를 확인했다. 48개였다.

앱마다 다른 종류의 인사이트가 들어왔다. 가계부 앱은 STABLE이라 매출 이상치 감지가 돌았고, 루틴 앱은 GROWING이라 경쟁앱 변화 감지가 같이 돌았다. 갓 출시한 앱 하나는 SEED라서 키워드 자동 생성 인사이트만 나왔다. 단계가 다르니까 인사이트 종류도 달랐다.

그 중에 하나가 눈에 들어왔다. 가계부 앱에 대한 인사이트였는데, “지난 14일간 ‘가계부’ 관련 키워드 클러스터에서 경쟁앱 3개가 메타데이터를 동시에 업데이트했고, 이 시점부터 가계부 앱의 해당 키워드 순위가 평균 8단계 하락했다”는 내용이었다. 신뢰도 뱃지는 상관관계. [근거 보기]를 눌렀더니 실제 날짜와 각 앱의 변경 이력이 나왔다. 데이터가 맞는지 직접 확인했다. 맞았다.

그 인사이트 카드 아래에 복사 버튼이 달린 키워드 세트가 있었다. Claude가 경쟁 키워드 변화를 반영해서 새로 생성한 거였다. 복사해서 App Store Connect에 붙여넣었다. 이게 효과가 있을지는 모른다. 근데 이 흐름 자체가 — 변화 감지, 원인 가설, 대응 키워드 생성, 복사 — 전부 자동으로 됐다는 게 포인트다.

FAQ

Q. AI 그로스 에이전트가 정확히 뭔가요? 기존 분석 도구와 뭐가 다른가요?

기존 도구들은 숫자를 보여줘요. “다운로드 22% 하락”처럼요. AI 그로스 에이전트는 거기서 한 단계 더 나간다. 왜 내려갔는지 원인을 가설로 제시하고, 그 가설의 근거가 되는 데이터를 같이 보여줘요. 그리고 대응으로 바로 쓸 수 있는 결과물을 만들어줘요. “이렇게 바꾸면 좋겠어요”가 아니라 “이 텍스트를 복사해서 붙여넣으세요”처럼요.

Q. 신뢰도 뱃지(팩트/상관관계/제안)는 어떻게 구분하나요?

팩트는 데이터에서 직접 읽어온 것, 상관관계는 두 데이터 사이의 패턴에서 유추된 것, 제안은 분석 기반 AI 추론이에요. 팩트는 수치로 확인됐으니 믿어도 돼요. 상관관계는 연관성이 있지만 인과가 확정된 건 아니에요. 제안은 해볼 만하지만 틀릴 수 있어요. 뱃지를 보고 내가 얼마나 신뢰할지 판단하면 돼요.

Q. 인디앱 필터 기준이 왜 평점 수인가요?

평점 수는 다운로드 수와 비례해요. 1,000개 이상이면 이미 상당한 마케팅이 들어간 앱이고, 그런 앱은 인디 개발자가 비교 기준으로 삼으면 안 돼요. 마케팅 예산도 다르고 ASO 전략도 달라서 거기서 나온 패턴은 인디한테 적용이 안 돼요. 평점 50~1,000개 범위가 비슷한 조건에서 성공한 앱들이고, 그게 실제로 참고할 수 있는 비교 대상이에요.

Q. 성장 단계(SEED/GROWING/STABLE)는 어떻게 정해지나요?

매일 Cron이 돌 때 자동으로 판정해요. 데이터가 쌓인 기간, 누적 다운로드 수, 최근 트렌드 방향을 보고 세 단계 중 하나로 분류해요. 30일 미만이거나 다운로드가 500개 미만이면 SEED, 성장 트렌드가 올라가고 있으면 GROWING, 3개월 이상 안정적으로 쌓였으면 STABLE이에요. 단계가 달라지면 분석 종류도 달라져요.

Q. 주간 메일 리포트는 어떻게 만들었나요?

Resend + React Email + Vercel Cron 조합이에요. React Email을 쓰면 이메일 템플릿을 React 컴포넌트로 짤 수 있어서 인라인 스타일 지옥을 피할 수 있어요. after() 패턴으로 이메일 발송을 백그라운드 처리하고, vercel.json에 월요일 오전 8시 Cron을 추가했어요. 메일 안엔 지난 주 요약, 상위 인사이트 3개, 이번 주 액션 하나만 넣었어요. 길면 안 읽으니까요.

Q. 바이브코딩으로 이 정도 기능을 만들 수 있다는 게 진짜인가요?

직접 만들었으니까 진짜예요. 핵심은 만들고 싶은 게 명확하면 된다는 거예요. “AI가 원인을 알려주고 복사 가능한 결과물을 만들어준다”는 방향이 명확했어요. Claude가 구조를 잡아주고 코드도 써줬지만, 어떤 기능이 필요한지, 신뢰도 뱃지 같은 아이디어는 내가 판단한 거예요. 코딩 실력보다 판단력이 필요한 일이 됐어요.

대시보드 다음

Apsity가 지금 하는 일을 정리하면 이렇다. 매일 새벽 3시에 데이터를 가져오고, 저녁 7시 30분에 AI 분석이 돌아간다. 월요일 아침 8시엔 주간 리포트가 이메일로 온다. 대시보드를 열기 전에 이미 지난 한 주 요약과 이번 주 액션이 메일함에 들어와 있다.

이걸 만들기 전엔 데이터를 보러 갔다. 이제는 데이터가 뭘 해야 할지를 들고 온다. 대시보드를 안 열어도 월요일 아침에 이미 흐름이 잡혀 있다. 귀찮아서 만들었는데, 만들고 나면 더 적게 일해도 더 많이 알게 되는 구조가 된다.

다음에 귀찮아지는 게 생기면 EP.04가 될 거다.

이 글은 2026년 3월에 작성됐다. Apsity는 현재 서비스 중이며 내용은 업데이트될 수 있다.

관련 글: 귀찮은개발자 EP.02 · 귀찮은개발자 EP.01 · Cursor vs Windsurf vs Codex 비교