코드는 영수증이 도착하기 전까지는 비즈니스가 아니다
AI 서비스 수익화 72시간의 기록
새벽 3시, 화면 속 코드는 엉켜 있었고 머릿속은 하얗게 비어 있었습니다.
믿었던 AI 코딩 파트너 Claude가 긴 문맥을 놓치기 시작했습니다. 고칠수록 버그가 증식하는 ‘개미지옥’이었습니다. 변수명이 제멋대로 바뀌고, 방금까지 되던 로직이 다음 순간 깨졌습니다.
그 순간 깨달았습니다. 이건 코딩의 문제가 아니었습니다.
localhost라는 온실을 벗어나, 실제 돈이 오가는 production이라는 야생으로 나가는 과정이었습니다. 그리고 1인 개발자에게 야생은 늘 가혹합니다.
1. 환각에 빠진 AI, 그리고 전환점
처음엔 순조로웠습니다. Claude와의 협업은 마법 같았죠. 제가 의도를 설명하면 코드가 술술 나왔습니다.
하지만 프로젝트가 커지자 이상한 일이 벌어지기 시작했습니다. 고쳤던 로직이 되돌아가고, 존재하지 않는 함수를 호출하고, “방금까지 되던 것”이 다음 순간 터졌습니다. 전형적인 AI 환각 증상이었습니다.
새벽 3시, 저는 화면을 멍하니 보고 있었습니다. 더 이상 코드를 시킬 수가 없었습니다.
“코딩을 더 시키기 전에, 설계를 다시 잡자.”
저는 파트너를 ChatGPT(메타철부지)로 바꾸고, 코드보다 먼저 배포 환경과 환경 변수(Secrets)의 정의부터 다시 시작했습니다.
이 과정에서 뼈아프게 배웠습니다. 1인 개발자가 무너지는 이유는 실력이 아니라 **‘복잡도 통제 실패’**인 경우가 많다는 것을요.
2. 결제 연동이라는 벽
AI 심층 리포트를 단순히 ‘만드는’ 것과 ‘파는’ 것은 완전히 다른 문제였습니다. 결제 시스템이 흔들리면 모든 게 무너집니다.
개발자 친화적이라는 Polar를 선택했습니다. 하지만 연동은 예상보다 험난했습니다.
401 Unauthorized: 문이 열리지 않았다
처음 막힌 건 Polar API 호출이었습니다. 계속 401 에러.
“분명 키를 넣었는데?”라는 생각이 들수록 더 위험합니다. 제 경험상 이런 경우 90%는 키가 무효입니다. 코드가 아닙니다.
결론은 단순했습니다. Polar API 토큰이 만료된 상태였고, 재발급으로 즉시 해결됐습니다.
프로덕션의 첫 번째 룰: 키는 맞는 게 아니라, 검증돼야 한다.
422 Unprocessable Entity: 상품이 ‘비어 있었다’
401을 뚫자마자 422가 나왔습니다. 겉으로는 “상품 ID 문제”처럼 보였지만, 로그를 따라가 보니 더 정확한 진짜 원인이 있었습니다.
요청 payload에서 products: [null]
즉, POLAR_PRODUCT_ID가 런타임에 주입되지 않았던 것입니다.
“대시보드에서 복사했는데 왜?”가 아닙니다. Production 환경 변수에 값이 들어가 있지 않거나, 다른 환경(Preview)에만 들어간 상태였던 겁니다.
저는 Polar의 상품 페이지 URL에서 정확한 Product UUID를 다시 확인했고, Cloudflare Pages의 Production 환경 변수로 재등록(삭제 후 재추가)한 뒤에야 422가 사라졌습니다.
환경 변수는 ‘설정했다’가 아니라, 런타임에서 확인돼야 한다.
TypeScript가 발목을 잡다
마지막 관문은 배포였습니다. 로컬에선 잘 도는데, Cloudflare Pages 빌드에서 터졌습니다.
원인은 의외로 단순했습니다. Pages Functions에서 env 타입을 지정하지 않으면 기본 타입에 ASSETS만 잡혀서, env.DB나 env.POLAR_PRODUCT_ID 같은 접근이 전부 TypeScript 에러로 빌드를 깨뜨립니다.
해결은 명확했습니다. debug-env 엔드포인트에 PagesFunction<Env> 타입을 명시해서 빌드가 통과하게 만들었습니다.
그리고 런타임에서 hasPolarProduct=true, len=36을 확인하며 ‘주입 성공’을 확정했습니다.
초록색 “Success”가 뜨는 순간, 저는 거의 체감했습니다. 프로덕션에서 ‘초록불’은 감정이 아니라 증거라는 것을요.
3. 0원 결제, 하지만 실전과 똑같이
배포가 성공해도, 제 PC에서만 테스트하면 의미가 없었습니다.
캐시, 로그인 상태, 개발자 습관… 모든 것이 결과를 왜곡할 수 있으니까요. 그래서 가장 객관적인 테스터를 불렀습니다.
가족의 핸드폰.
와이파이를 끄고 LTE로 접속했습니다. 그리고 내부 테스트용으로 100% 할인 쿠폰을 만들었습니다.
중요한 건 ‘0원’이 아니었습니다. 프로세스였습니다.
결제 페이지로 이동하는지, 할인 적용이 되는지, 카드 인증 플로우가 정상인지, 결제 완료 후 리포트가 생성되고 PDF 저장까지 이어지는지…
짧은 몇 초 동안 서버는 바쁘게 움직였습니다. 주문을 만들고, 결제를 확정하고, 리포트를 생성하고, PDF를 전달했습니다.
그리고 화면에는 AI가 분석한 심층 리포트(PDF)가 떠 있었습니다.
“된다”가 아니라 “사용자가 쓸 수 있다”가 증명되는 순간이었습니다.
4. 0원 영수증, 비즈니스의 시작
몇 초 뒤, 제 메일함에 영수증 메일이 도착했습니다.
(발신자는 Polar를 통해 온 chulbuji-labs)
금액은 $0.00.
하지만 의미는 0이 아니었습니다.
이 영수증은 제 코드가 사용자의 주문을 받고, 할인/결제 인증 과정을 통과시키고, 약속한 디지털 상품(PDF)을 전달했다는 ‘완결된 거래의 증명서’였기 때문입니다.
이 순간부터 저는 더 이상 “만드는 사람”만이 아니었습니다.
굴러가는 구조를 운영하는 사람이 되었습니다.
마치며: 완벽한 코드가 아니라, 닫힌 루프가 사업을 만든다
이번 72시간의 결론은 한 줄입니다.
“코드는 기능을 만들고, 영수증은 비즈니스를 증명한다.”
그리고 이 과정에서 얻은 현실적인 배움 3가지:
• Production 문제의 70%는 코드가 아니라 설정(환경 변수/도메인/권한)이다. • “돌아간다”는 감상이 아니라 로그/응답/주입 확인으로 증명해야 한다. • 서비스는 개발자 테스트가 아니라 일반 사용자(가족/지인) 테스트에서 완성된다.
다음 스텝
이제 할 일:
• 운영용으로 디버그 로그/엔드포인트를 정리하고 • chulbuji.com(블로그) → insight.chulbuji.com(서비스) 연결을 SEO 관점에서 고정하고 • 이 런칭 기록을 공개해 “첫 10명의 사용자”를 맞이할 준비를 합니다.
마지막으로, 이 글을 읽고 **“나도 내 상황을 객관적으로 정리해보고 싶다”**고 느꼈다면, 여기서 직접 확인할 수 있습니다:
https://insight.chulbuji.com/form
참고: 이 리포트는 의학적/법적 진단이 아니라, 사용자의 입력을 구조화해 실행 관점으로 정리하는 도구입니다. 위기 상황이라면 전문 기관/전문가의 도움을 우선으로 두는 것이 안전합니다.