앱 12개 수익 확인하다 지쳐서 대시보드 직접 만들었다
App Store Connect에서 앱 12개 수익을 매일 확인하다 지쳐서 대시보드를 직접 만들었다. App Store Connect API 연결,
2026년 3월 · 귀찮은개발자 EP.02
App Store에 앱이 12개 올라가 있다. 처음엔 하나였다. 하나가 둘이 되는 건 자연스럽고, 둘이 다섯이 되는 건 의욕 때문이고, 다섯이 열두 개가 되는 건 멈추지 않은 결과다. 앱이 늘어나는 건 나쁘지 않은데, 문제는 그 숫자만큼 확인할 게 같이 늘어난다는 거다.
나는 이 12개 앱의 수익, 다운로드, 키워드 순위를 한 화면에서 보는 대시보드를 직접 만들었다. Apsity라는 이름을 붙였다. App Store Connect API를 연결하고, 매일 새벽에 데이터를 자동으로 가져오게 만들었다. 이 글은 그 과정의 개발 일지다.

직접 만든 대시보드 — 앱 12개 데이터가 한 화면에 / GoCodeLab
– App Store Connect의 Sales and Trends 합산 기능이 2026~2027에 걸쳐 deprecated 예정
– 사라지기 전에 내 데이터 파이프라인을 직접 만들기로 함
– Claude에 요구사항 두 줄 던져서 Next.js + Supabase + Vercel 아키텍처 확정
– App Store Connect API를 JWT 인증으로 연결, TSV 데이터 파싱
– Vercel Cron으로 매일 새벽 3시 자동 동기화, after() 패턴으로 12개 앱 병렬 처리
– 이제 아침에 일어나면 어제 데이터가 이미 들어와 있다
App Store Connect가 뭐가 문제인가
오해하면 안 되는 게 있다. App Store Connect의 Sales and Trends에서는 전체 앱 합산 데이터를 볼 수 있다. 현재 기준으로 Units, Proceeds, Sales를 전체 앱 묶어서 보는 게 가능하다. 앱 하나하나 들어갈 필요 없이 합산 수치가 나온다. 그러니까 “ASC에서 합산이 안 된다”는 말은 지금 시점에서는 틀리다.
문제는 이게 곧 사라진다는 거다. 2026년 3월, Apple이 Analytics 대규모 업데이트를 발표하면서 Sales and Trends 대시보드를 단계적으로 deprecated 한다고 했다. 구독 관련 대시보드는 2026년 중반부터, 나머지는 2027년에 걸쳐 없어진다. 새로 만든 Analytics에는 앱별 지표가 100개 넘게 생겼다. 코호트 분석, 피어 벤치마크, 구독 데이터까지. 근데 여러 앱을 한 화면에서 합산해서 보는 기능은 빠졌다.
나는 사라지기 전에 직접 만들기로 했다. 어차피 내가 원하는 건 ASC보다 더 구체적이었다. 합산 수치만이 아니라, 키워드 순위 추적, 경쟁앱 변화 감지, AI 분석까지 한 곳에서 보고 싶었다. 그 중 합산 대시보드가 제일 먼저 필요했고, 그래서 여기서부터 시작했다.
Claude한테 요구사항을 던졌다
아키텍처를 혼자 잡지 않았다. Claude 창을 새로 열고, 요구사항을 그냥 썼다. “iOS 앱 여러 개 운영하는 개발자가 수익을 한 화면에서 보고 싶다. App Store Connect API 연결. 키워드 순위 추적.” 두 줄이었다.
Claude가 스택 제안을 돌려줬다. 그게 이거다.
프레임워크: Next.js — 웹페이지와 서버를 하나로 만드는 도구
DB: Supabase — 클라우드 데이터 창고. 엑셀 같은 느낌인데 실시간 동기화
인증: Supabase Auth — 로그인/세션 관리를 알아서 해줌
배포: Vercel — 코드 올리면 바로 인터넷에 뜨는 호스팅. 타이머 기능 내장
차트: Recharts — 그래프/차트 그리는 라이브러리
첫날 저녁에 기본 구조가 잡혔다. 실제로 뭔가 되는 속도가 빠르다 보니, 오히려 더 많은 결정을 해야 했다. 그 결정들을 Claude가 CLAUDE.md에 기록해뒀다. 세션이 끊겨도 “왜 Supabase를 인도 리전이 아니라 US East로 다시 만들었는지” 같은 맥락이 남아 있었다. EP.01에서 만든 그 자동화가 여기서도 그대로 쓰였다.
App Store Connect API 연결 — JWT 인증이라는 첫 번째 벽
App Store Connect API는 그냥 접근할 수 있는 게 아니다. JWT 토큰을 직접 만들어야 한다. JWT는 “나 진짜 개발자야”를 증명하는 디지털 신분증 같은 거다. Apple이 발급한 비공개 열쇠로 서명하고, 유효 시간을 넣고, Apple이 지정한 암호화 방식(ES256)에 정확히 맞춰야 한다. 읽으면 뭔 말인지는 알겠는데, 직접 만들면 중간에 뭔가 하나는 꼭 틀린다.
Claude한테 Apple 공식 문서 링크를 주고, “이 JWT 생성해줘, TypeScript로”라고 했다. 돌아온 코드를 붙여넣고 실행했더니 첫 번째 API 호출이 됐다. 응답이 왔다. TSV 형식으로. TSV는 엑셀처럼 칸이 나뉜 텍스트 파일인데, 구분자가 탭이다. 거대한 텍스트 덩어리가 터미널에 찍혔을 때, 그게 데이터라는 걸 알면서도 일단 기뻤다. 뭔가 연결이 됐다는 감각이었다.
그다음 문제는 그 데이터를 읽어내는 거였다. 판매 리포트의 컬럼이 수십 개다. 핵심은 productType이라는 숫자 필드 하나다. 1이면 다운로드, 7이면 인앱결제, 8이면 구독. Apple이 이 숫자로 거래 종류를 구분한다. 이걸 코드 여기저기에 흩어두면 나중에 Apple이 스펙을 바꿀 때 전부 찾아서 고쳐야 한다. Claude가 categorize()라는 분류 함수 하나를 만들자고 했다. 이 함수만 거쳐서 종류를 판별하고, 나머지 코드는 결과만 보는 방식이다. 지금도 그렇게 돌아가고 있다.
다국가 앱은 매출 합산이 생각보다 복잡하다. 한국에서 팔리면 원화, 일본에서 팔리면 엔화로 들어온다. 직접 환율로 환산하면 환율 변동 때문에 어제보다 오늘 수익이 낮게 잡힐 수 있다. Apple이 이미 proceeds(USD)로 환산한 값을 제공한다. Claude가 그 값만 집계하자고 제안했다. 환율 왜곡 없이 일관된 달러 기준으로 트렌드를 볼 수 있다. 맞는 말이라 그대로 썼다.
Vercel Cron 자동화 — 자는 동안 데이터가 쌓인다
API 연결이 됐고, 데이터를 읽어낼 수 있게 됐다. 이제 이걸 자동으로 매일 돌려야 한다. Vercel에는 Cron이라는 기능이 있다. 스마트폰 알람처럼, “매일 이 시간에 이걸 실행해”라고 설정해두면 알아서 돌아간다.
“/api/cron/daily-sync” → 매일 새벽 3시 (UTC 18:00)
“/api/cron/daily-rank” → 매일 새벽 3:30 — 키워드 순위 수집
“/api/cron/cleanup” → 주 1회 — 오래된 데이터 자동 정리
한국 새벽 3시가 UTC 18시다. 하루 데이터가 마무리되는 시점에 자동으로 돌게 맞췄다. 배포하고 첫날 밤, 자다가 Vercel 로그를 확인했다. Cron이 돌았고, API가 호출됐고, 데이터가 Supabase에 들어가 있었다. 아침에 대시보드를 열었을 때 어제 다운로드 숫자가 이미 들어와 있었다. 직접 한 게 없는데 데이터가 와 있다는 감각이 생각보다 이상했다. 좋은 쪽으로.
근데 문제가 생겼다. 앱이 12개니까 동기화 작업이 12번 돌아야 한다. Vercel Cron은 기본적으로 10초 안에 끝나지 않으면 강제로 잘라버린다. 하나씩 순서대로 처리하면 20초가 넘는다. 10초에서 잘리면 나머지 앱들은 동기화가 안 된 채로 끝난다.
Claude한테 상황을 설명했더니 next/server after() 패턴을 제안했다. 편의점에서 손님이 계산을 마치면 “감사합니다”부터 말하고, 영수증 출력은 그 다음에 하는 것처럼 — 응답을 먼저 보내고 실제 처리는 백그라운드에서 한다.
export async function GET() {
after(async () => {
await Promise.all(apps.map(app => syncApp(app)))
})
return NextResponse.json({ ok: true }) // 타임아웃 전에 즉시 응답
}
“작업 완료”를 즉시 돌려준다. Vercel 입장에서는 응답이 왔으니 타임아웃 없이 넘어간다. 실제 동기화는 after() 안에서 백그라운드로 돌아간다. 12개 앱이 동시에 시작한다. 은행 창구가 1개면 12명이 줄 서야 하는데, 12개 창구가 동시에 열리는 것처럼. 적용했더니 타임아웃 없이 됐다.
대시보드에 뭐가 들어가는가
만든 결과물을 좀 보여주면 이렇다. 대시보드를 열면 가장 먼저 보이는 건 메트릭 카드 4개다. 오늘 총 다운로드, 총 수익(USD), 활성 구독자 수, 키워드 최고 순위. 각 카드 안에 7일간 추이가 작은 그래프로 들어가 있다.
아래로 내리면 앱별 성과 테이블이 있다. 앱 이름, 어제 다운로드, 어제 매출이 한 줄에 나온다. 수익 기준 내림차순이다. Revenue 탭에선 앱 판매, 인앱결제, 구독이 색상별로 구분된 스택 차트가 30일간 나온다. Keywords 탭에선 키워드별 순위와 난이도가 산점도로 나온다. X축이 난이도, Y축이 순위. 왼쪽 위 사분면이 “난이도 낮고 순위 높은” 골든 키워드다.
const opportunity = (1 – difficulty/100) * (200 – rank) / 2
// 난이도 = 해당 키워드 상위 10개 앱의 평점 수 기반
// 평점 수가 적으면 인디앱이 뚫을 수 있는 구간
if (score >= 70) → ‘Hard’
if (score >= 40) → ‘Medium’
else → ‘Easy’
경쟁앱 추적 탭도 만들었다. 같은 카테고리 앱을 최대 5개까지 등록하면 매일 메타데이터 변경(이름, 부제, 설명)을 비교한다. Countries 탭에서는 어떤 나라에서 다운로드가 느는지 보고, Subscriptions 탭에서는 활성 구독자 수와 갱신율을 확인한다. 이것들은 ASC 새 Analytics에서 앱별로 제공하는 것과 겹치는 부분도 있다. 차이는 내 12개 앱 전체를 한 곳에서 보는 거다.

Revenue 탭 — 매출 유형별 30일치를 자동 집계 / GoCodeLab
데이터를 어떻게 쌓을 것인가
Cron이 돌면서 데이터가 매일 들어오기 시작했다. 근데 데이터가 쌓이면 새로운 문제가 생긴다. DB 비용이 올라가고, 오래된 데이터는 잘 안 보게 되고, 정리해야 하는데 그것도 수동으로 하기 싫다. cleanup Cron이 여기서 나왔다. 매주 일요일 새벽, 일정 기간이 넘은 데이터를 자동으로 지운다. 이것도 Claude가 먼저 제안한 거다. 혼자였으면 데이터가 한참 쌓이고 나서야 생각했을 거다.
키워드 순위 수집도 신경 쓸 게 있었다. iTunes Search API를 루프 안에서 빠르게 호출하면 429(rate limit)가 터진다. 요청 사이에 300ms 지연을 넣어서 해결했다. ASC 데이터도 가끔 지연이 있다. 어제 데이터가 새벽 3시에 아직 안 나올 수 있다. 재시도 로직을 넣어서, 데이터가 없으면 6시간 뒤에 다시 가져오게 했다.
바이브코딩이 그냥 “Claude가 코드 써줘서 빠르다”가 아닌 게 이 지점이다. 나중에 고통받을 포인트를 미리 잡아준다. cleanup Cron, rate limit 보호, 재시도 로직 같은 건 혼자였으면 문제가 터지고 나서야 만들었을 거다.
앱이 나를 위해 일한다
지금 Apsity가 어떻게 돌아가는지 정리하면 이렇다. 매일 한국 새벽 3시에 Cron이 App Store Connect API를 호출한다. 전날 다운로드, 매출, 국가별 데이터가 Supabase에 들어간다. 30분 뒤에 등록한 키워드 순위가 수집된다. 아침에 대시보드를 열면, 내가 자는 동안 12개 앱의 어제 데이터가 전부 들어와 있다. 합산도 자동이고, 랭킹 변동도 바로 보인다.
이걸 만드는 데 며칠이 걸렸다. 만들고 나서 매일 아침 15분이 생겼다. 15분 × 365일이 91시간이고, 91시간이면 다음 앱 하나를 만들 수 있는 시간이다. 그리고 Apple이 Sales and Trends를 deprecated 하는 시점이 오면 ASC에서 크로스앱 합산을 보는 방법 자체가 없어진다. 그전에 직접 파이프라인을 갖고 있는 게 맞다.
귀찮은 게 생기면 만들면 된다
이 시리즈 내내 반복되는 패턴이 하나 있다. 귀찮은 게 생기면 만들면 된다. 지금은 만드는 것 자체가 예전보다 훨씬 덜 귀찮다. JWT, Cron, after() 같은 용어가 낯설어도 상관없다. Claude한테 “이게 뭔데, 어떻게 하면 돼?”라고 하면 설명해주고 코드도 써준다. 공식 문서 링크 주면 읽고 구현해준다. 타임아웃 문제가 생겼을 때도 상황만 설명하면 해결 방법이 나왔다. 내가 할 일은 판단이다. 이 방향이 맞는지, 이 방법이 우리 상황에 맞는지.
Apsity를 만들고 나서 다음 귀찮은 게 생겼다. 대시보드를 열면 데이터는 있는데, “그래서 뭘 해야 하지?”라는 질문이 남았다. 숫자가 내려간 건 알겠는데 왜인지는 여전히 내가 파야 한다. EP.03에서는 그 판단까지 자동화한 AI 그로스 에이전트 얘기를 한다.
FAQ
Q. App Store Connect에서도 전체 앱 합산 수익을 볼 수 있지 않나요?
맞다. 현재 Sales and Trends에서는 전체 앱 합산이 가능하다. 근데 Apple이 2026년 중반부터 Sales and Trends를 단계적으로 없앤다고 발표했다. 새 Analytics는 앱별 개별 분석만 지원하고, 크로스앱 합산은 빠져 있다. 지금은 되지만 곧 안 된다. 사라지기 전에 내 파이프라인을 만들어둔 거다.
Q. App Store Connect API 연결이 어렵지 않나요?
처음 접하면 낯설다. JWT 토큰 생성, ES256 서명, TSV 파싱이 필요하다. 근데 Claude한테 Apple 공식 문서 링크를 주면 코드를 바로 써준다. 반나절이면 API 연결이 된다. 직접 문서를 뒤지는 것보다 훨씬 빠르다.
Q. 바이브코딩으로 앱을 만드는 데 코딩 실력이 필요한가요?
코딩 실력보다 만들고 싶은 게 명확한 게 더 중요하다. 뭘 만들지 말로 설명할 수 있으면 나머지는 Claude가 상당 부분 처리해준다. 판단하고 방향을 잡는 건 여전히 사람 몫이다.
Q. Vercel 무료 플랜으로도 Cron 자동화가 가능한가요?
가능하다. 다만 무료 플랜의 타임아웃이 짧아서, after() 패턴처럼 즉시 응답하고 백그라운드에서 처리하는 방식을 쓰면 12개 앱도 타임아웃 없이 동기화된다.
Q. 직접 만드는 것보다 기존 ASO 도구를 쓰는 게 낫지 않나요?
목적에 따라 다르다. Sensor Tower나 AppFollow 같은 도구는 기능이 많지만 가격이 인디 개발자한테 부담이 될 수 있다. 자기한테 필요한 기능만 정확히 구현하고 싶다면 직접 만드는 게 맞을 수 있다. 무엇보다 만드는 과정 자체가 배움이 된다.
마무리
대시보드를 만들었고, 매일 새벽에 데이터가 자동으로 들어온다. App Store Connect 탭 12개 열어놓고 왔다 갔다 하던 아침 루틴이 사라졌다. 그리고 Apple이 Sales and Trends를 없애는 시점이 오더라도, 내 데이터 파이프라인은 그대로 돌아간다.
근데 대시보드를 3일 쓰다 보니 다른 종류의 귀찮음이 생겼다. 숫자는 보이는데 “그래서 뭘 해야 하지?”가 남았다. EP.03에서는 그 얘기를 한다.
이 글은 2026년 3월에 작성됐다. 내용은 업데이트될 수 있다.