주요 콘텐츠로 건너뛰기
AI 튜토리얼

ShrimpReel로 AI 바이럴 동영상 SaaS 구축 및 출시

ShrimpReel을 로컬에서 실행하고 바이럴 동영상 트렌드에 맞게 커스터마이징하는 방법을 알아보세요. 결제 및 동영상 생성 기능을 구성하고, Cloudflare 리소스를 프로비저닝하며, 안전하게 배포하고, 각 키워드별 사이트를 업스트림 템플릿과 동기화하는 방법을 다룹니다.

ShrimpReel로 AI 바이럴 동영상 SaaS 구축 및 출시

ShrimpReel이란?

ShrimpReel은 업로드한 사진 한 장을 바이럴 형식에 맞춘 AI 생성 동영상으로 변환하는 웹사이트를 구축하기 위한 오픈 소스 SaaS 템플릿입니다. 권장 워크플로는 유행하는 키워드마다 별도의 저장소를 만들고, 사이트 구성과 이중 언어 콘텐츠를 변경하고, 미디어를 교체한 뒤, 완성된 애플리케이션을 Cloudflare에 배포하는 것입니다.

이 스택은 프론트엔드와 서버 측 렌더링에 TanStack Start, React 19, Tailwind CSS 4를 함께 사용합니다. Hono API는 /api/* 경로, 미디어 제공, robots 지시어, 사이트맵, IndexNow 인증을 처리합니다. 서버 진입점은 src/server.ts입니다.

애플리케이션은 Cloudflare Workers, D1, R2, KV, Queues, Rate Limiting, Cron Triggers를 중심으로 설계되었습니다. 영어 페이지는 /에서 제공되며, 중국어 페이지는 /zh에서 이용할 수 있습니다.

프로젝트 상태: README에 따르면 전체 워크플로는 로컬 단위 테스트와 Playwright 종단 간 테스트를 통과하지만, 아직 프로덕션 배포로 검증되지는 않았습니다. 실제 서비스와의 개별 통합을 신뢰하기 전에 ROADMAP.md를 검토하세요.

주요 기능

계정, 결제 및 크레딧

  • Google One Tap과 localhost 전용 개발자 로그인을 포함한 Google 로그인.
  • 크레딧 팩 및 선택 가능한 월간 또는 연간 구독.
  • 크레딧 원장, 교환 코드, 추천 링크, 결제 내역, 인쇄 가능한 주문 상세 정보, 계정 삭제 및 데이터 내보내기.
  • 기본 결제 제공업체인 Waffo Pancake 또는 대체 제공업체인 Dodo Payments.
  • 크레딧 자동 회수가 적용되는 부분 및 전액 환불.

동영상 생성

  • 기본 동영상 제공업체로 사용하는 fal.ai의 대기열 API.
  • yir.ai를 통한 선택적 라우팅.
  • 로컬 개발 및 테스트 중 템플릿 동영상을 복사하는 모의 제공업체.
  • 생성 대기열, 배달 불능 대기열 및 생성 실패 시 크레딧 자동 반환.
  • 사용자가 동영상별로 활성화할 수 있는 공개 동영상 공유 페이지.

성장, 관리 및 운영

  • UTM 값과 광고 클릭 식별자를 사용하는 최초 접점 및 최종 접점 어트리뷰션.
  • 방문부터 생성까지의 퍼널 및 동의 기반 GA4 이벤트.
  • 사용자, 주문, 생성 작업, 결제 이벤트, 삭제 요청, 신고, 이메일, 감사 기록, 추천, 런타임 설정 및 연결 테스트를 위한 관리자 인터페이스.
  • 제공업체 비용 및 매출총이익 보고.
  • 점검 모드, 공지, 일일 생성 한도, 상태 알림, 브라우저 오류 보고 및 결제 알림.
  • 매일 D1을 R2에 백업.

안전, 보존 및 SEO

  • 업로드 검토 및 동영상의 AI 생성 라벨.
  • 7일 후 사진 자동 삭제 및 30일 후 동영상 자동 삭제.
  • 동일한 원본 사진으로 만들어진 동영상을 삭제하고 해당 사진을 차단하는 48시간 삭제 요청 대기열.
  • 문의 및 신고 양식의 Turnstile 지원.
  • 표준 URL, hreflang 메타데이터, JSON-LD, 사이트맵, 법률 페이지, 가이드, 관련 문서 및 코드 분할 방식의 현지화 문구.
  • npm run seo:check를 통해 사용할 수 있는 사이트 전체 SEO 린터.

사전 요구 사항

Node.js와 npm 11.19 이상을 설치하세요. 이전 npm 버전은 package-lock.json을 나중에 지속적 통합 환경에서 npm ci를 실패하게 만드는 형식으로 다시 작성할 수 있습니다.

프로덕션 배포에는 Cloudflare 계정, 결제 제공업체 계정, 동영상 제공업체 API 키 및 Google OAuth 인증 정보도 필요합니다. 번들 스크립트로 자리 표시자 미디어를 다시 생성할 때만 FFmpeg가 필요합니다.

ShrimpReel을 로컬에서 설치하고 실행하기

1. 종속 요소를 설치하고 로컬 변수 만들기

npm install
cp .dev.vars.example .dev.vars

.dev.vars를 열고 최소한 SESSION_SECRET을 설정하세요. 프로덕션과 스테이징에서는 32자 이상의 강력한 값이 필요합니다. README에서는 다음 명령으로 생성할 것을 권장합니다.

openssl rand -hex 32

2. 로컬 데이터베이스 및 미디어 저장소 준비

npm run seed:local

이 명령은 D1 마이그레이션을 적용하고 seed/templates/*.mp4의 파일을 로컬에서 에뮬레이션되는 R2 저장소에 업로드합니다.

3. 개발 서버 시작

npm run dev -- --host 127.0.0.1

http://127.0.0.1:3000을 여세요. Windows에서는 127.0.0.1을 명시적으로 사용하면 테스트 도구가 localhost를 IPv6로 확인하는 경우도 방지할 수 있습니다.

개발 서버를 0.0.0.0에서 실행하거나 인터넷에 직접 노출하지 마세요. 개발자 로그인, 모의 결제 및 /api/dev/*는 직접적인 localhost 요청에만 사용하도록 설계되었습니다.

기본 워크플로 사용해 보기

기본 로컬 구성은 PAYMENT_PROVIDER=mock, VIDEO_PROVIDER=mock, MODERATION_PROVIDER=mock을 사용합니다. 따라서 카드를 청구하거나 외부 동영상 서비스에 작업을 제출하지 않고도 제품을 테스트할 수 있습니다.

  1. 로그인 페이지를 열고 프로덕션 외부에 표시되는 개발자 로그인을 사용합니다.
  2. 크레딧 팩을 선택합니다. 모의 결제는 실제 청구 없이 결제를 시뮬레이션합니다.
  3. 사진을 업로드하고 생성을 시작합니다.
  4. 모의 동영상 제공업체는 AI 모델을 호출하는 대신 시드된 템플릿 동영상을 복사합니다.
  5. 대시보드를 열어 생성된 동영상, 크레딧 원장, 결제 기록 및 공유 설정을 확인합니다.

업로드 거부를 시뮬레이션하려면 mockOutcome=reject를 사용하여 업로드 양식을 제출하세요. 로컬에서 Turnstile을 비활성화하려면 TURNSTILE_SITE_KEY를 비워 두세요.

현재 로그인한 사용자의 미디어에 대한 보존 기간 정리도 테스트할 수 있습니다.

POST /api/dev/sweep
Content-Type: application/json

{"days": 8}

로컬 이메일 전송은 시뮬레이션됩니다. 다음 명령으로 아웃박스를 확인하세요:

GET /api/dev/emails?to=user@example.com&ref=<order-or-takedown-id>

새로운 트렌드 사이트 만들기

1. 업스트림 기록을 유지하면서 저장소 복제하기

git clone https://github.com/qianshuixia/shrimpreel.git moonhop
cd moonhop
git remote rename origin upstream
git remote add origin git@github.com:<owner>/moonhop.git

향후 템플릿 업데이트를 병합하려면 GitHub의 템플릿 버튼을 사용하지 마세요. 이 방식으로 만든 저장소는 소스 저장소와 기록을 공유하지 않습니다. 일반적인 복제와 upstream 원격 저장소를 사용하면 병합 기준이 유지됩니다.

2. 사이트 스캐폴더 실행하기

먼저 드라이 런으로 시작해 제안된 변경 사항을 검토한 다음 --write를 추가하세요:

node scripts/new-site.mjs --keyword "Moon Hop" --domain moonhop.ai --keywords "AI dance video,Moon Hop filter"
node scripts/new-site.mjs --keyword "Moon Hop" --domain moonhop.ai --keywords "AI dance video,Moon Hop filter" --write

스캐폴더는 site.ts, wrangler.jsonc의 Cloudflare 리소스 이름, 패키지 이름을 업데이트합니다. 배포별 식별자를 초기화하고 템플릿의 스테이징 구성을 제거합니다. 그런 다음 남은 수동 작업의 체크리스트를 출력합니다.

3. 가격 및 생성 구성하기

src/config/site.ts를 편집하세요. packages의 크레딧 팩, subscriptionsEnabled 스위치, 구독 plans, 사용 가능한 durations, video.falModel을 검토하세요.

사이트에서 일회성 팩만 판매하려면 subscriptionsEnabled를 false로 설정하세요. 팩은 anchorPriceCents를 사용해 취소선이 그어진 비교 가격을 표시할 수 있지만, README에서는 실제로 해당 가격에 판매된 적이 있는 가격을 나타내야 한다고 안내합니다. 새 사이트에서는 일반적으로 설정하지 않습니다.

4. 현지화된 콘텐츠 다시 작성하기

src/content/en.ts와 src/content/zh.ts에서 트렌드에 맞춰 작성된 문구를 교체하세요. 최소한 히어로 섹션, 설명, 아이디어, FAQ, 포함된 두 아티클을 다시 작성해야 합니다. 선택 사항인 문제 및 비교 블록도 다시 작성하거나 null로 설정하세요.

기존 텍스트 전체에서 키워드만 바꾸는 방식은 피하세요. 템플릿은 기계적으로 복제된 사이트가 검색 엔진에서 대규모 콘텐츠 악용으로 간주될 수 있다고 명시적으로 경고합니다.

아티클을 추가하려면 먼저 site.ts의 articles 섹션에 메타데이터 항목을 만든 다음 모든 로케일에 일치하는 콘텐츠 키를 추가하세요. 아티클은 가이드 허브, 사이트맵, 구성된 관련 아티클 링크에 자동으로 포함됩니다. 홈 페이지에서 링크하므로 기존 trend 및 howTo 항목은 유지하세요.

5. 모든 플레이스홀더 미디어 교체하기

  • 소스 생성 클립은 <template.id>-<seconds>s.mp4 패턴을 사용해 seed/templates/에 넣으세요.
  • public/demo/의 홈 페이지 동영상과 포스터를 교체하세요.
  • public/og.png와 public/favicon.svg를 교체하세요.
  • 직접 제작했거나 라이선스를 취득한 데모 미디어만 사용하고, 출처를 site.examples.*.credit에 기록하세요.

FFmpeg를 사용할 수 있다면 다음 명령으로 프로젝트의 원본 플레이스홀더 에셋을 다시 생성하세요:

node scripts/generate-placeholder-media.mjs

template.id를 변경한 후에는 seed/templates/에서 더 이상 사용하지 않는 템플릿 파일을 삭제하세요.

실제 프로바이더 구성하기

런타임 변수

wrangler.jsonc에서 비밀이 아닌 프로덕션 변수를 설정하세요. 중요한 값으로는 SITE_URL, APP_ENV=production, PAYMENT_PROVIDER, VIDEO_PROVIDER, MODERATION_PROVIDER, TURNSTILE_SITE_KEY, ADMIN_EMAILS, EMAIL_FROM, 제품 매핑, GOOGLE_CLIENT_ID가 있습니다.

결제 프로바이더의 제품 가격이 기준이 됩니다. 사이트에 표시되는 가격은 프로바이더 대시보드와 동기화된 상태로 유지해야 합니다. 제품 매핑은 구성된 각 팩 또는 플랜을 프로바이더 제품 ID와 연결합니다.

시크릿

선택한 통합에 따라 시크릿에는 SESSION_SECRET, GOOGLE_CLIENT_SECRET, Waffo 자격 증명, Dodo 자격 증명, FAL_KEY, 선택 사항인 YIR_API_KEY, 중재용 선택 사항인 OPENAI_API_KEY, TURNSTILE_SECRET_KEY가 포함될 수 있습니다.

개별 시크릿은 다음 명령으로 설정하세요:

npx wrangler secret put <NAME>

또는 프로덕션 변수 파일을 복사해 완성하고, 계획을 검토한 다음 누락된 시크릿을 적용하세요:

cp .dev.vars.example .dev.vars.production
node scripts/sync-secrets.mjs
node scripts/sync-secrets.mjs --apply

동기화 스크립트는 시크릿 값을 출력하지 않습니다. --overwrite를 지정하지 않는 한 기존 원격 시크릿은 유지됩니다.

Cloudflare 리소스 프로비저닝하기

각 키워드 사이트마다 별도의 리소스 세트를 만드세요. 이름은 wrangler.jsonc의 바인딩과 일치해야 합니다.

npx wrangler d1 create <name>
npx wrangler r2 bucket create <name>-media
npx wrangler kv namespace create <name>-kv
npx wrangler queues create <name>-jobs
npx wrangler queues create <name>-jobs-dlq
npm run db:migrate:remote
npx wrangler r2 object put <name>-media/templates/<file>.mp4 --file seed/templates/<file>.mp4 --content-type video/mp4 --remote

생성된 D1 데이터베이스 ID와 KV 네임스페이스 ID를 wrangler.jsonc에 복사하세요. 각 사이트의 속도 제한 namespace_id도 Cloudflare 계정 내에서 고유해야 합니다.

프로젝트에 설명된 R2 수명 주기 규칙을 구성하여 업로드된 사진과 생성된 동영상에 7일 및 30일의 보존 기간이 적용되도록 합니다. 트랜잭션 이메일을 사용하려면 발신 도메인도 Cloudflare Email Service에 등록해야 합니다.

검증 및 배포

로컬 품질 검사 실행

npm run typecheck
npm test
npm run test:e2e
npm run seo:check

배포하기 전에 구성 진단 도구를 실행합니다.

npm run doctor

진단 도구는 환경, 도메인, 선택한 공급자, 제품 매핑, Cloudflare 리소스 바인딩, 큐, Cron 구성, 필수 시크릿 이름, 적용되지 않은 마이그레이션, 해결되지 않은 TODO(site) 마커를 검사합니다. 원격 검사를 의도적으로 사용할 수 없는 경우 --offline을 사용합니다.

배포 및 스모크 테스트 실행

npm run deploy
SMOKE_BASE_URL=https://<domain> npm run test:smoke

npm run deploy는 먼저 사전 배포 검사를 실행합니다. 배포 후 Cloudflare에서 사용자 지정 도메인을 연결하고 SITE_URL이 site.domain과 정확히 일치하는지 확인합니다. 표준 URL, 사이트맵, 동일 출처 CSRF 검사는 이 일치 여부에 따라 달라집니다.

사용자 지정 도메인이 정상적으로 작동하면 workers_dev와 preview_urls를 false로 설정합니다. 그렇지 않으면 프로덕션 Worker가 동일한 D1 및 R2 리소스를 사용하는 공개 Cloudflare 개발 URL과 버전 URL을 통해 계속 액세스될 수 있습니다.

SEO 출시 작업 완료

npm run seo:check -- --base https://<domain> --production
npm run seo:indexnow -- --submit

site.seo.indexNowKey를 구성한 후에만 IndexNow 명령을 실행합니다. Google Search Console과 Bing Webmaster Tools에서 도메인을 인증한 다음 https://<domain>/sitemap.xml을 제출합니다.

고급 팁

프로덕션에서 목 사용 방지

선택한 공급자가 mock으로 남아 있으면 프로덕션과 스테이징 환경은 503 응답으로 결제, 생성, 업로드를 거부합니다. 해당 환경에서는 개발 로그인, 목 결제 라우트, 개발 API 엔드포인트가 404를 반환합니다. 이는 npm run doctor 실행을 대신하는 것이 아니라 안전 장치로 취급해야 합니다.

패치를 복사하지 말고 템플릿 업데이트 병합

사이트별 작업은 src/config/site.ts, src/content/*, public/*, seed/, wrangler.jsonc 및 패키지 이름에 유지합니다. 공통 수정 사항은 템플릿에서 수행한 후 각 사이트에 병합해야 합니다.

git fetch upstream
git show upstream/main:scripts/sync-plan.mjs > .tmp/sync-plan.mjs
node .tmp/sync-plan.mjs
git merge --no-ff upstream/main
npm install
npm run typecheck
npm test
npm run test:e2e
npm run db:migrate:remote

스쿼시 병합, 리베이스 또는 체리픽 대신 병합 커밋을 사용합니다. 동기화 계획은 git merge-base HEAD upstream/main에 의존합니다. 병합을 기록할 때 커밋 메시지 끝에 Template-sync: <template commit sha>를 추가합니다.

배포 중 하위 호환성 유지

마이그레이션이 실행된 후 배포에 실패하면 새 Worker 버전은 롤백할 수 있지만 D1 마이그레이션은 자동으로 되돌려지지 않습니다. 롤백이 가능하도록 마이그레이션을 이전 애플리케이션 버전과 호환되게 유지합니다.

필요한 경우 번들된 Claude Code 워크플로 사용

저장소에는 트렌드에 맞는 사이트를 스캐폴딩하는 new-hot-site 스킬, 템플릿 변경 사항을 병합하는 sync-upstream 스킬, 출시 전 및 라이브 검사를 수행하는 읽기 전용 launch-audit 스킬이 포함되어 있습니다. 이러한 도구는 수동 검토를 대신하지 않습니다. 생성된 카피, 라이선스가 있는 미디어, 도메인, 공급자 제품, OAuth 설정, 이메일 등록, 수명 주기 정책은 여전히 검증해야 합니다.

핵심 로직을 변경하기 전에 프로젝트 문서 검토

크레딧, 결제 이행, 이중 언어 콘텐츠, 마이그레이션 또는 엔드투엔드 테스트를 수정하기 전에 AGENTS.md를 확인합니다. 추가 세부 정보는 docs/env.md, docs/payments.md, docs/subscriptions.md, docs/SEO_AUDIT.md, docs/SAAS_VIDEO_FEATURES.md에서 확인할 수 있습니다. README에 따르면 이 문서들은 현재 중국어로 작성되어 있습니다.

결론

ShrimpReel은 생성 큐, 결제, 크레딧, 관리, 보존, 컴플라이언스 워크플로, 분석, SEO, Cloudflare 운영을 포함하는 키워드 중심 AI 동영상 SaaS를 위한 상당한 출발점을 제공합니다. 안전한 목 워크플로부터 시작하고, 사이트별 모든 계층을 사용자 지정하며, 자리 표시자 콘텐츠를 라이선스가 있는 자산으로 교체하고, 모든 공급자 및 Cloudflare 설정을 검증한 후, 전체 테스트, 진단, SEO 및 스모크 테스트 절차가 통과된 경우에만 배포합니다.