
카메라를 사고팔 때마다 번개장터, 중고나라, 당근마켓을 각각 열어서 가격을 비교하는 데 30분씩 쓰고 있었다. "소니 A7M4 중고 시세가 얼마야?"라는 간단한 질문에 답하려면 탭 3개를 열고, 검색하고, 눈대중으로 평균을 내야 한다.
이걸 한 곳에서 볼 수 있는 사이트를 만들면 되지 않을까? 그래서 CamPrice를 만들었다.
| 영역 | 기술 |
|---|---|
| 프론트엔드 | Next.js 16 (App Router) + Tailwind CSS + Recharts + TanStack Query |
| 백엔드 | FastAPI (Python) + SQLAlchemy Async + PostgreSQL + Redis |
| 크롤러 | httpx (번개장터/중고나라) + Playwright (당근마켓) |
| 인프라 | Docker Compose (로컬), Vercel (프론트 배포) |
| AI 도구 | Claude Code (Opus 4.6) + gstack 스킬 |
gstack은 Claude Code 위에서 동작하는 오픈소스 스킬 프레임워크다. 기획(/office-hours), 리뷰(/plan-ceo-review, /plan-eng-review), QA(/qa), 보안 감사(/cso) 같은 스킬을 슬래시 커맨드로 실행할 수 있어서, 코딩 외의 작업도 AI에게 맡길 수 있다.
클로드코드에 깃허브 링크 전달하고, '이거 쓰고싶어. 가져와줘' 라고 하면 바로 사용할 수 있다.
Claude Code의 gstack /office-hours 스킬로 프로젝트 방향을 잡았다. YC 오피스아워처럼 날카로운 질문을 던져주는 스킬인데, 이 과정에서 중요한 인사이트를 하나 얻었다.
"이 서비스는 리텐션이 불가능하다."
카메라를 사고파는 건 1년에 한두 번이다. 유저가 매일 돌아올 이유가 없다. 그래서 SEO가 유일한 유저 획득 채널이고, 모델 상세 페이지가 곧 제품의 전부라는 결론이 나왔다. "소니 A7M4 중고 시세"를 검색하면 CamPrice가 나와야 한다.
이 판단이 이후 모든 설계 결정의 기준이 됐다.
<초기 프로토타입 — 텍스트만 있고 데이터도 없는 상태에서 시작했다>
바이브코딩에서 제일 신기했던 부분이다. 코드를 쓰기 전에 4가지 관점의 리뷰를 먼저 돌렸다.
/plan-ceo-review — "스코프가 너무 작다"며 가격 알림, 신선도 배지, GA4 추가를 제안. 세 개 다 수락했다./plan-design-review — 초기 디자인 완성도를 5/10으로 평가하고, 7/10까지 올리는 구체적인 방법을 제시./design-consultation — 색상, 폰트, 간격을 정의한 DESIGN.md 파일을 생성. 이후 모든 UI 작업의 기준이 됐다./plan-eng-review — 테스트 17개 계획, N+1 쿼리 잠재 이슈, 에러 복구 전략까지 짚어줬다.보통 혼자 만드는 사이드 프로젝트에서 이런 리뷰를 받을 일이 없는데, AI가 CEO/디자이너/시니어 엔지니어 역할을 동시에 해주니까 설계 품질이 확 올라갔다.
여기서 병렬 에이전트를 썼다. Claude Code가 백엔드(Lane A)와 프론트엔드(Lane B)를 동시에 구현하는 건데, 각각 6분 만에 끝났다.
백엔드에서는 가격 스냅샷 서비스, 7일 rolling median 시세 계산, 매물 만료 감지(크롤링에서 사라지면 sold 처리), 가격 알림 MVP까지 구현했다. 프론트에서는 SEO 메타데이터, sitemap, 스켈레톤 로더, 신선도 배지, GA4 이벤트, 접근성까지 한 번에 들어갔다.
pytest 19개 테스트를 돌렸고, 1.9초 만에 전부 통과.
기능은 금방 만들었는데, 데이터 품질이 문제였다. "소니 A7M4 중고 시세"를 보여줘야 하는데 케이스 2만원, 렌즈 30만원짜리가 섞여서 평균 시세가 엉망이 됐다.
이걸 해결하려고 하이브리드 필터링을 도입했다.
1차로 크롤링할 때 악세사리 키워드(케이스, 배터리, 충전기, 스트랩 등 25개+)를 걸러내고, 2차로 IQR 통계 필터를 적용해서 가격 이상치를 자동으로 제거했다.
예: A7M4 매물 [2만, 120만, 130만, 140만, 150만, 160만, 500만]
→ IQR로 2만원(악세사리)과 500만원(오류) 자동 제거
→ 규칙에 없는 새로운 악세사리도 가격 기반으로 잡아냄
모델 매칭도 문제였다. "캐논 EOS 450D"가 "EOS R5"로 잡히는 식의 오매칭이 있었는데, 짧은 별칭(r5, z5 같은 3글자 이하)을 fuzzy matching에서 제외하고 cutoff를 60에서 75로 올려서 해결했다. 155건이던 오매칭이 33건으로 줄었다.
이런 판단은 AI가 대신 해줄 수 없다. "이 가격은 악세사리다"라는 도메인 지식은 직접 카메라를 사고파본 사람만 할 수 있는 거다.
초기 프로토타입은 텍스트와 데이터만 나열된 상태였다. /design-consultation에서 만든 DESIGN.md를 기준으로 전면 리디자인을 했다.
홈페이지에 남색(#1E40AF) 히어로 배너를 넣고, 실시간 매물 이미지를 12초 간격으로 페이드 전환하는 콜라주를 추가했다. 그 아래에 인기 모델 8개의 실시간 가격과 썸네일, 방금 올라온 매물 목록, 하단 통계(2,400+ 매물, 76 모델, 3 플랫폼)를 배치했다.
<리디자인 완료 홈페이지 — 히어로 + 인기 모델 + 최근 매물 + 통계>
핵심인 모델 상세 페이지도 다듬었다. 가격 카드(IQR 적용된 정확한 시세), 가격 추이 차트, 플랫폼별 필터, 쿠팡 신품 비교 카드까지 넣었다. SEO로 유입된 유저가 이 페이지 하나에서 "사도 되는 가격인지"를 판단할 수 있게 만드는 게 목표였다.
<.Sony A6000 상세 — 가격 카드, 추이 차트, 쿠팡 비교, 매물 목록>
전체 페이지에 파란 헤더 바를 통일하고, 검색/브랜드 페이지도 같은 톤으로 맞췄다.

<검색 페이지 — 매물 사진 + 가격 + 플랫폼 표시>

<브랜드 목록 — 10개 브랜드, 모델 수 표시>
<.Sony 브랜드 — 미러리스/컴팩트 카테고리별 그룹화>
모바일도 전부 반응형으로 다듬었다. 터치 타겟 44px, 하단 네비게이션 바 추가.
![]() | ![]() |
|---|
번개장터와 중고나라는 httpx로 비교적 쉽게 크롤링했는데, 당근마켓은 달랐다. CSR(Client-Side Rendering)이라 HTML을 받아봤자 빈 껍데기만 온다. Playwright로 실제 브라우저를 띄워서 파싱해야 했다.
# Playwright로 당근마켓 웹 페이지 파싱
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
# 가격 span → 부모 카드 → 제목/이미지/링크 추출
25개 주요 도시 × 36개 검색어 조합으로 전국 카메라 매물을 커버한다. 당근마켓 특성상 지역별로 검색해야 해서 조합이 많지만, 병렬 처리로 수집 시간은 짧게 유지했다.
다시 /office-hours를 돌려서 수익화 방향을 탐색했다. 핵심은 트래픽 없이도 시작할 수 있는 수익원부터 붙이는 것이다.
1단계로 쿠팡파트너스 제휴 링크를 모델 상세 페이지에 넣었다. "신품으로 구매하고 싶다면?" 카드를 매물 사이에 자연스럽게 배치해서, 중고 시세를 보다가 "차라리 새 걸 살까?" 하는 유저를 잡는 구조다. 이건 트래픽이 적어도 전환이 나올 수 있다.
6개월 후 프리미엄 구독(월 3,900원, 가격 알림/실시간 알림), 12개월 후 AdSense 추가가 다음 단계. 목표는 월 50~100만원 부업 수익.
배포 전에 /cso 스킬로 보안 감사를 돌렸다. CRITICAL 0건, SQL 인젝션/XSS/시크릿 노출 전부 안전. HIGH 1건(CORS * 설정)과 MEDIUM 1건(Rate limit 미적용)이 나왔는데, 둘 다 배포 시 도메인 제한과 함께 적용할 예정이다.
혼자 만드는 프로젝트에서 보안 감사까지 받을 수 있다는 게 바이브코딩의 장점이다. 보통은 "나중에 하자"고 넘어가는 부분인데, AI가 5분 만에 해주니까 안 할 이유가 없다.
/qa 스킬로 브라우저 기반 QA를 3회 반복했다. 실제로 헤드리스 브라우저가 사이트를 돌아다니면서 콘솔 에러, 깨진 레이아웃, 접근성 문제를 찾아준다.
1회차 Health Score 92에서 시작해서, 발견된 버그를 고치고 다시 돌리고, 3회차에 98까지 올렸다. 콘솔 에러 0, 데스크톱/모바일 전체 통과.
하루(+ 알파) 만에 만든 것:
| 스킬 | 용도 | 횟수 |
|---|---|---|
/office-hours | 기획 + 수익화 전략 | 2회 |
/plan-ceo-review | 스코프/전략 리뷰 | 1회 |
/plan-design-review | 디자인 리뷰 | 1회 |
/design-consultation | 디자인 시스템 생성 | 1회 |
/plan-eng-review | 엔지니어링 리뷰 | 1회 |
/qa | 브라우저 QA 테스트 | 3회 |
/cso | 보안 감사 | 1회 |
/design-review | UI/UX 개선점 찾기 | 1회 |
속도가 압도적이다. 기획→리뷰→구현→테스트→QA→보안감사를 하루에 끝냈다. 병렬 에이전트로 백엔드와 프론트를 동시에 구현하고, 리뷰도 CEO/엔지니어/디자이너 관점을 한 번에 받는다.
반복 개선이 빠르다. "이거 좀 이상한데?" → 즉시 수정 → 확인 → 커밋. 이 사이클이 몇 분 단위로 돌아간다. QA도 마찬가지. 브라우저가 직접 돌아다니며 버그를 찾고, 고치고, 다시 돌리는 걸 3회 반복하는 데 전부 합쳐서 30분도 안 걸렸다.
도메인 지식은 대체 불가다. "케이스 2만원이 시세에 섞이면 안 된다"는 판단, "이 필터 UX가 직관적이지 않다"는 감각은 직접 카메라를 사고파본 사람만 할 수 있다. AI는 구현은 빠르게 해주지만, 뭘 구현해야 하는지는 알려주지 않는다.
외부 연동은 시행착오가 필요하다. 당근마켓 CSR 크롤링, 쿠팡 제휴 링크 형식 같은 건 문서가 부족하거나 없어서 직접 삽질해야 한다. 배포(VPS 세팅, 도메인)도 마찬가지.
바이브코딩은 "코드를 대신 짜주는 것"이 아니라, "제품 감각이 있는 사람이 실행 속도를 10배로 높이는 것"이다. 뭘 만들어야 하는지 아는 사람이 써야 진짜 가치가 나온다.
지금까지는 로컬 개발 환경에서 동작하는 상태다. 다음 단계는 인프라 세팅이다. VPS에 백엔드 + 크롤러 + DB를 올리고, 도메인을 연결하고, 크롤러가 40분마다 자동으로 돌아가도록 만들어야 한다. 프론트는 Vercel에 이미 배포되어 있으니, 백엔드 API만 퍼블릭으로 열리면 실서비스가 된다.