LDBD
/
전체 글

첫 일주일에 만든 것: 사용자 0명짜리 리더보드에 봇 18개를 넣었다

스펙 토론이 끝났다. 이제 진짜 코드를 짜야 했다. Postgres·Next.js·Supabase·RLS 같은 단어를 거의 처음 만난 비개발자가 첫 일주일에 무엇을 만들었는지.

지난 글에서 1,600줄짜리 스펙을 만든 이야기를 썼다. 그 스펙을 들고 진짜 코드를 짜기 시작한 첫 일주일 이야기다.

솔직히 첫 일주일 안에 서비스가 동작할 거라고 생각하지 않았다. Postgres, Supabase, RLS, Edge Function, App Router 같은 단어는 거의 처음 봤고, 검색을 해도 설명 안에 또 모르는 단어가 나왔다.

그런데 일주일 뒤에는 로그인, 자산 가격 수집, 예측 제출, 자동 채점, 리더보드까지 다 붙어 있었다.

내가 직접 친 코드는 거의 없었다. 그런데 이상하게도, 매 순간 결정하고 있는 사람은 나였다. 코드는 빨리 나왔고, 문제는 내가 무엇을 만들지·무엇을 버릴지·무엇을 먼저 보여줄지 충분히 빨리 결정해야 한다는 점이었다.

단어가 먼저 막혔다

검색해서 읽어도 한 페이지 안에 모르는 다섯 가지 개념이 깔려있어서 이해하기 어려웠다. 그래서 모르는 단어가 나올 때마다 그냥 Claude한테 한 줄로 설명해달라고 했다.

처음엔 Postgres와 Supabase 차이부터 헷갈렸다. 나중엔 이렇게 받아들였다 — Postgres는 실제 데이터가 들어가는 데이터베이스고, Supabase는 그 Postgres 위에 로그인·권한·함수 실행 같은 걸 얹어주는 서비스. 둘 다 직접 써 본 적은 없지만 이 정도면 따라갈 수 있었다.

스키마(schema)는 처음엔 추상적이었다. 결국엔 이렇게 받아들였다 — 표가 어떤 모양인지 미리 정해두는 설계도. “예측은 자산 ID, 방향, 기간, 결과를 가진다” 같은 약속을 적어두는 것이다. 이게 먼저 정해져야 데이터가 어디에 어떻게 들어갈지 정해진다.

RLS도 처음 들어봤는데 결국엔 이렇게 이해했다 — 사용자가 자기 데이터만 건드릴 수 있게 DB 안쪽에 세워두는 문지기. 다만 문지기를 잘 세워둬야 안전한 거지, RLS만 켜놓는다고 자동으로 안전해지는 건 아니다.

cron job은 단어 자체가 어렵진 않았는데 “주기적으로 만료된 예측을 채점” 같은 작업을 정해진 주기로 자동 실행해주는 트리거다, 정도로 알고 나면 충분했다. 정확한 정의는 더 복잡하겠지만, 첫 주의 나에게는 이 정도 이해면 작업이 됐다.

단어가 좀 익숙해지니 Claude Code가 만드는 파일이 외계어처럼은 안 보였다. 직접 짜라면 당연히 못 짠다. 그래도 “아, 지금 DB 테이블을 만들고 있구나”, “아, 이건 사용자가 자기 예측만 보게 막는 코드구나” 정도는 따라갈 수 있었다.

어떤 도구로 시작했나

스택 추천을 물어봤더니 답이 짧았다. Next.js + Supabase + Tailwind + shadcn/ui. 1인 개발자가 운영비 적게 들고 인증·DB가 한 번에 갖춰진 조합으로 가장 무난하다는 이유.

처음 들어보는 단어가 절반이었지만 일단 추천대로 시작했다. 안 맞으면 그때 바꾸지, 라는 마음으로.

사용자 0명짜리 리더보드

리더보드 만든 다음 화면에 띄우고 보니 이상했다. 아무도 없으니까 빈 표였다. 빈 표를 본 새 사용자가 “아 아무도 안 쓰는구나” 하고 떠나는 게 보였다. 머릿속에서.

해결책은 세련되진 않았지만 직설적이었다. 사람이 없으면, 일단 봇을 넣자.

VOO, QQQ, GLD, BTC-USD, KODEX 200, KODEX 코스닥150 — 6개 자산에 각각 “항상 상승”, “항상 하락”, “랜덤” 세 가지 단순 전략을 붙이면 18개가 나온다. 그리고 2016년부터의 가격 데이터로 backfill을 돌렸다 — 실제 사용자가 과거에 예측한 건 아니지만, “이 18개 봇이 지난 10년 동안 매일 예측했다면 결과가 어땠을 것인가”를 계산해 과거 기록처럼 채웠다. 일종의 시뮬레이션 리더보드였다.

그래서 사용자 0명짜리 리더보드가 누군가 실제로 예측하고 스코어를 확인할 수 있는 보드처럼 보였다.

의외의 부수 효과가 하나 있었다. 그 데이터에서 자연스럽게 통계가 나왔다 — 매일 “상승”만 누르는 봇의 적중률이 62%. 그게 지금 LDBD 랜딩에 박혀 있는 도발 메시지의 출처다 — “매일 ‘상승’만 누르는 봇의 적중률이 62% 입니다. 상승만 누르는 봇도 못 이기면, 당신의 예측은 어떤 의미가 있을까요?”

점수가 화면에 안 맞았다

스펙 문서 안에서는 Skill Rating이 멋져 보였다. 통계적으로 그럴듯했고, 체스 Elo에서 온 개념이라 신뢰감도 있었다. Claude도 추천했다.

그런데 화면에 올리는 순간 문제가 보였다.

Skill Rating 1500

이 숫자를 처음 보는 사람이 무슨 생각을 할까? 1500이면 잘하는 건가, 평균인가, 1800이면 대단한 건가. 설명을 읽어야 이해되는 1등 지표라면, 첫 화면의 지표로는 실패다.

결국 평균 점수(avg score)를 1차 랭킹으로 올리고 Skill Rating은 화면에서 거의 숨겼다. 평균 점수는 “예측 한 건당 평균 +0.3점” 같이 직관적이다. AI가 틀린 게 아니었다. 내가 처음에 “좋은 지표”와 “좋아 보이는 화면 지표”를 구분하지 못했다.

결과를 알려야 다시 온다

예측 서비스에는 이상한 문제가 하나 있다. 사용자는 오늘 예측하지만, 결과는 며칠 뒤에 나온다. 그 며칠 뒤에 사용자가 다시 안 들어오면 채점 시스템이 아무리 잘 돌아가도 의미가 없다.

그래서 자동 채점되는 순간 사용자한테 인앱 알림이 가도록 했다 — 헤더의 종 아이콘에 빨간 점. 그리고 자산 페이지에 커뮤니티 센티먼트라는 작은 섹션을 추가했다. “다른 사람들은 VOO 1주일 뒤를 어떻게 보는가 — 상승 12명, 하락 5명” 같은 식으로 본인이 다수파인지 소수파인지 보이게 했다.

사실 그때도, 이 글을 쓰는 지금도 사용자는 거의 없다. 알림을 받을 사람이 없는 셈이다. 그래도 이 구조는 먼저 깔아두기로 했다 — 사용자가 들어온 뒤에 붙이면 늦을 것 같았다.

일주일 끝나고

일주일이 끝났을 때 LDBD에 남아 있던 결과물은 대략 이랬다.

  • 이메일·구글 로그인
  • 주식·ETF·코인 약 600개 자산이 매일 자동으로 가격 수집됨
  • 예측 제출 폼 (자산 / 방향 / 기간)
  • 매시간 돌면서 만료된 예측을 채점하는 cron job
  • 리더보드 (평균 점수 + 숨긴 Skill Rating)
  • 10년치 시뮬레이션을 등에 업은 18개 베이스라인 봇
  • 알림 + 커뮤니티 센티먼트

나는 코드를 하나도 안 짰다. 대신 계속 물었다. 이 기능이 지금 진짜 필요한가? 이 숫자가 사용자에게 이해되는가? 빈 화면을 처음 본 사람은 무슨 생각을 할까? 어떤 엣지케이스를 그냥 무시할까?

첫 일주일이 끝나고 나서야 조금 알 것 같았다.

Claude Code는 코드를 정말 빨리 만든다. 그런데 그 속도가 빨라질수록 내가 내려야 할 결정도 같이 빨라진다. 어떤 지표를 첫 화면에 둘지. 빈 리더보드를 그대로 둘지, 봇으로 채울지. 사용자가 다시 돌아오게 하려면 무엇을 알려줘야 할지.

코딩을 거의 안 했다고 해서, 제품을 안 만든 건 아니었다. 첫 일주일 동안 내가 한 일은 코드를 치는 일이 아니라, 계속 선택하는 일이었다.

다음 4편

다음 4편부터는 방향이 조금 바뀐다. LDBD 자체를 만드는 이야기에서, 이제는 다른 AI들을 LDBD에 붙이는 이야기로 넘어간다.

Claude Desktop + MCP, 로컬 LLM, ChatGPT Connector, OpenAI API 직접 호출까지 네 가지 방식을 모두 해봤다. 같은 일을 네 방식으로 해보니 각각 장단점이 꽤 달랐다. 다음 글부터 하나씩 정리한다.


LDBD에 직접 예측을 등록해보고 싶다면 메인 페이지에서 시작할 수 있다. 무료, 가입 없이 리더보드 구경 가능.

vibe-codingclaude-codefirst-week