|
|
||
|---|---|---|
| components | ||
| docs | ||
| nginx | ||
| public | ||
| server | ||
| services | ||
| src | ||
| .env.example | ||
| .env.production.example | ||
| .gitignore | ||
| App.tsx | ||
| CLAUDE.md | ||
| DEPLOY.md | ||
| GEMINI.md | ||
| PLAN.md | ||
| README.md | ||
| SALES_MANUAL.md | ||
| SERVER_DEPLOY_GUIDE.md | ||
| USER_MANUAL.md | ||
| components.json | ||
| deploy.sh | ||
| index.html | ||
| index.tsx | ||
| metadata.json | ||
| multi_domain_deploy.sh | ||
| nginx.castad.conf | ||
| nginx_bizvibe.conf | ||
| package-lock.json | ||
| package.json | ||
| plan.md | ||
| postcss.config.js | ||
| saas.png | ||
| setup-nginx-castad1.sh | ||
| start.sh | ||
| startserver.sh | ||
| tailwind.config.js | ||
| test_api.sh | ||
| tsconfig.json | ||
| types.ts | ||
| vite.config.ts | ||
README.md
CaStAD (카스타드) - AI-Powered Pension Marketing Video Platform
CaStAD는 펜션/숙박업소를 위한 AI 기반 마케팅 비디오 자동 생성 및 멀티 플랫폼 통합 관리 SaaS 플랫폼입니다. Google Gemini AI와 Suno AI를 활용하여 광고 카피, 음악, 영상을 자동으로 생성하고, OAuth 2.0 기반 YouTube, TikTok 채널 연동을 통해 직접 업로드까지 지원합니다.
📚 목차 (Table of Contents)
공통
Part A. 개발자 매뉴얼 (Developer Manual)
- A1. 시스템 아키텍처
- A2. 기술 스택
- A3. 프로젝트 구조
- A4. 데이터베이스 스키마
- A5. API 명세
- A6. 인증 시스템
- A7. 영상 생성 파이프라인
- A8. 개발 환경 설정
- A9. 코드 기여 가이드
Part B. 운용자 매뉴얼 (Operator Manual)
- B1. 시스템 요구사항
- B2. 설치 및 배포
- B3. 환경 변수 설정
- B4. 외부 서비스 연동
- B5. 관리자 대시보드
- B6. 사용자 관리
- B7. 플랜 및 크레딧 관리
- B8. 사진 관리 시스템
- B9. 시스템 모니터링
- B10. 백업 및 복구
- B11. 트러블슈팅
Part C. 사용자 매뉴얼 (User Manual)
- C1. 시작하기
- C2. 회원가입 및 로그인
- C3. 펜션 등록하기
- C4. 영상 만들기
- C5. 영상 옵션 상세
- C6. YouTube 연동
- C7. TikTok 연동
- C8. Instagram 연동
- C9. 영상 관리
- C10. 에셋 관리
- C11. 계정 설정
- C12. 구독 및 요금제
- C13. 자주 묻는 질문 (FAQ)
Part D. 마케터 매뉴얼 (Marketer Manual)
Part E. 영업사원 매뉴얼 (Sales Manual)
🌟 프로젝트 개요
비전
펜션 사업자가 전문 마케팅 지식 없이도 고품질 홍보 영상을 손쉽게 제작하고, YouTube, TikTok 등 멀티 플랫폼에 자동으로 배포할 수 있는 올인원 SaaS 플랫폼.
주요 사용 시나리오
1. 사업자 회원가입 → 펜션 정보 등록
2. 네이버/구글 지도 URL 입력 → 자동 정보 수집
3. AI가 광고 카피, 음악, 영상 생성
4. YouTube/TikTok 채널 연동 → 원클릭 업로드
5. 다국어 SEO 최적화 → 해외 고객 유입
6. 고급 통계 대시보드 → 성과 분석
✨ 핵심 기능
🎵 AI 다국어 음악 생성 (Suno AI v5)
6개 언어별 맞춤형 로고송/CM송을 자동 생성합니다.
| 언어 | 지원 장르 |
|---|---|
| 한국어 (KO) | K-Pop, 트로트, 발라드, 힙합, R&B, EDM, Jazz, Rock |
| 영어 (EN) | Pop, Country, Hip-Hop, R&B, EDM, Jazz, Rock, Ballad |
| 일본어 (JP) | J-Pop, 엔카, 애니메이션, Rock, Jazz, Ballad, EDM |
| 중국어 (CN) | C-Pop, Mandopop, 전통음악, 발라드, Hip-Hop, EDM |
| 태국어 (TH) | T-Pop, Luk Thung, Pop, Hip-Hop, Rock, EDM, Jazz |
| 베트남어 (VN) | V-Pop, 볼레로, Pop, Hip-Hop, Rock, EDM, Jazz |
오디오 모드 옵션:
| 모드 | 설명 |
|---|---|
| Song | 가사 포함 노래 생성 |
| Narration | TTS 내레이션 |
| Instrumental | 가사 없는 악기 연주 |
음악 길이:
- Short: 30초 이하 (Verse → Chorus → Outro)
- Full: 약 2분 (Verse 1-2 → Chorus → Outro)
🤖 AI 콘텐츠 생성 (Gemini 2.5 Flash)
| 기능 | 설명 |
|---|---|
| 다국어 광고 카피 | 6개 언어 마케팅 헤드라인 4개 자동 생성 |
| 리뷰 기반 마케팅 | 고객 리뷰 + 평점 → AI 마케팅 설명 작성 |
| 이미지 검수/필터링 | Gemini Vision으로 최고 품질 이미지만 선별 |
| 비디오 배경 생성 | Imagen Video로 동영상 배경 자동 생성 |
| 광고 포스터 생성 | Imagen 3으로 AI 포스터 이미지 생성 |
| 사업 정보 검색 | Google Maps Tool로 펜션 정보 자동 수집 |
| 🧬 비즈니스 DNA 분석 | Google Search Grounding으로 브랜드 DNA 자동 추출 |
🧬 비즈니스 DNA 분석 (NEW!)
펜션의 브랜드 아이덴티티를 AI가 자동으로 분석합니다.
| 분석 항목 | 설명 |
|---|---|
| 톤앤매너 | 브랜드 커뮤니케이션 스타일 (프리미엄, 감성적, 모던 등) |
| 타겟 고객 | 주요/부차 타겟층, 연령대, 라이프스타일 특성 |
| 브랜드 컬러 | 이미지 기반 컬러 팔레트 자동 추출 (5-6색) |
| 키워드 | SEO 최적화 핵심 키워드 + SNS 해시태그 |
| 시각적 스타일 | 인테리어/외관/분위기 분석 + 추천 사진 스타일 |
| 차별화 포인트 | 경쟁력 있는 고유 가치 제안 (USP) 3-5개 |
기술 스택:
- Google Search Grounding: 실시간 웹 검색으로 최신 정보 수집
- Gemini 2.5 Flash: 멀티모달 분석 (텍스트 + 이미지)
- DNACard 컴포넌트: 분석 결과 시각화
📸 스마트 이미지 관리 (NEW!)
| 기능 | 설명 |
|---|---|
| 확장된 크롤링 | 네이버 플레이스에서 최대 30장 자동 수집 |
| 다중 소스 | 메뉴, 업체, 객실, 방문자 이미지 통합 수집 |
| 영구 저장 | 크롤링된 이미지를 펜션 프로필에 자동 저장 |
| 자동 로드 | 펜션 선택 시 저장된 이미지 즉시 불러오기 |
| 선택적 사용 | 전체/개별/랜덤 이미지 선택 모드 |
🎙️ AI 음성 합성 (TTS)
| 설정 | 옵션 |
|---|---|
| 성별 | 남성 (Male), 여성 (Female) |
| 연령대 | 청년 (Young), 중년 (Middle) |
| 톤 | Professional, Bright, Calm, Energetic |
음성 캐릭터:
- 여성 + 밝은/활기찬 → Zephyr (밝고 활기찬 여성음)
- 여성 + 차분한 → Kore (침착한 여성음)
- 남성 + 전문적 → Charon (전문적인 남성음)
- 남성 + 활기찬 → Fenrir (에너지 있는 남성음)
🎬 영상 생성 옵션
화면 비율:
| 비율 | 용도 |
|---|---|
| 16:9 | YouTube, 웹사이트 |
| 9:16 | TikTok, Instagram 릴스, YouTube Shorts |
| 1:1 | Instagram 피드, 정사각형 |
텍스트 효과 (11종 + Custom):
| 효과 | 설명 | 용도 |
|---|---|---|
| Cinematic | Fade 효과, 영화식 | 고급스러운 느낌 |
| Neon | Glow 효과, 핑크 네온 | 현대적, 화려함 |
| Glitch | 디지털 노이즈 | 트렌디, 청년층 |
| Typewriter | 타자기 애니메이션 | 임팩트, 강조 |
| Bold | 굵은 대문자 이탤릭 | 강렬함 |
| Motion | 움직이는 효과 | 역동성 |
| LineReveal | 상하 라인 최소주의 | 세련됨 |
| Boxed | 박스 테두리 | 정리된 느낌 |
| Elegant | 세리프 이탤릭 | 우아함 |
| BlockReveal | 검은 배경 흰 텍스트 | 팝아트, 강조 |
| Custom | AI 분석 기반 | 사용자 정의 CSS |
화면 전환 효과 (4종):
| 효과 | 설명 |
|---|---|
| Mix | 부드러운 혼합/페이드 |
| Zoom | 확대/축소 전환 |
| Slide | 밀어내기 전환 |
| Wipe | 닦아내기 전환 |
🏠 펜션 카테고리 시스템 (9종)
| 카테고리 | 설명 |
|---|---|
| 풀빌라 | 프라이빗 수영장 보유 |
| 오션뷰 | 바다 전망 |
| 산장/계곡 | 자연 속 힐링 |
| 독채 | 프라이빗 공간 |
| 커플펜션 | 로맨틱 분위기 |
| 가족펜션 | 단체 숙박 최적화 |
| 애견동반 | 반려동물 환영 |
| 글램핑 | 캠핑 + 럭셔리 |
| 한옥펜션 | 전통미 |
복수 선택 가능 - AI가 카테고리에 맞는 마케팅 카피와 음악 스타일을 자동 추천
📺 멀티 플랫폼 연동
| 플랫폼 | 인증 | 기능 |
|---|---|---|
| YouTube | OAuth 2.0 | 직접 업로드, 플레이리스트 관리, SEO 자동 생성 |
| TikTok | OAuth 2.0 | Direct Post, Inbox 업로드, 프라이버시 설정 |
| ID/PW | 릴스 업로드, 주간 제한, 2FA 지원 |
💳 크레딧 시스템
| 플랜 | 가격 (월) | 월 크레딧 | 펜션 수 | 스토리지 |
|---|---|---|---|---|
| Free | 무료 | 10 | 1개 | 500MB |
| Basic | ₩29,000 | 15 | 1개 | 2GB |
| Pro | ₩89,000 | 75 | 5개 | 10GB |
| Business | ₩249,000 | 무제한 | 무제한 | 50GB |
📊 고급 통계 (v3.0)
| 기능 | 설명 |
|---|---|
| 대시보드 요약 | 전체 사용자, 영상 생성, 플랫폼 업로드 현황 |
| 사용자 성장 추이 | 일별/주별/월별 신규 가입자 트렌드 |
| 영상 생성 트렌드 | 시간대별 영상 생성 패턴 분석 |
| 플랫폼 업로드 통계 | YouTube/TikTok/Instagram 업로드 비교 |
| 크레딧 사용 분석 | 크레딧 소비 패턴 및 충전 요청 현황 |
| 플랜 분포 | 요금제별 사용자 분포 |
| Top 사용자 | 활동량 기준 상위 사용자 |
| 지역별 분포 | 펜션 지역별 분포 현황 |
| 수익 예측 | 구독 기반 예상 수익 분석 |
| 시스템 헬스 | 서버 상태, 리소스 사용량 모니터링 |
| 일일 스냅샷 | 매일 자동 통계 기록 |
| 펜션별 분석 | YouTube 조회수, 시청 시간 분석 |
📁 에셋 관리
| 에셋 타입 | 소스 |
|---|---|
| 이미지 | 업로드, 웹 크롤링, AI 생성 |
| 오디오 | Suno AI 생성, TTS |
| 비디오 | 렌더링 결과물 |
- 플랜별 스토리지 제한
- 자동 썸네일 생성
- 메타데이터 관리 (크기, 해상도, 길이)
🎪 축제 연동 시스템 (v3.2.0 신규)
펜션 근처 축제 정보를 자동으로 가져와 마케팅 콘텐츠에 반영합니다.
| 기능 | 설명 |
|---|---|
| 데이터 소스 | 한국관광공사 Tour API |
| 자동 동기화 | 관리자가 수동 또는 스케줄 동기화 |
| 지역 기반 추천 | 펜션 주소 기반 가까운 축제 자동 표시 |
| 행정구역 그룹핑 | 시/도 단위로 축제 목록 그룹화 |
| 콘텐츠 연동 | 선택한 축제가 가사/광고 카피에 자동 반영 |
축제 데이터 구조:
{
"id": 12345,
"title": "강릉 커피 축제",
"sido": "강원",
"sigungu": "강릉시",
"addr1": "강원특별자치도 강릉시 ...",
"event_start_date": "20241201",
"event_end_date": "20241215",
"first_image": "https://..."
}
API 엔드포인트:
| 엔드포인트 | 설명 |
|---|---|
GET /api/festivals |
축제 목록 조회 (sido, sigungu 필터) |
GET /api/festivals/grouped |
행정구역별 그룹 조회 |
GET /api/festivals/:id |
축제 상세 정보 |
POST /api/admin/sync/festivals |
축제 데이터 동기화 (관리자) |
💰 Google Cloud Billing 연동 (v3.2.0 신규)
BigQuery를 통해 실제 Google Cloud 비용을 실시간으로 추적합니다.
설정 단계:
- Google Cloud Console에서 Billing Export to BigQuery 활성화
- 서비스 계정 생성 및 BigQuery 권한 부여
google-billing-key.json파일을server/폴더에 배치- 환경 변수 설정
환경 변수:
GOOGLE_BILLING_KEY_PATH=./server/google-billing-key.json
GOOGLE_CLOUD_PROJECT_ID=your-project-id
GOOGLE_BILLING_DATASET_ID=billing_export
대시보드 기능:
| 기능 | 설명 |
|---|---|
| 서비스별 비용 | Vertex AI, Cloud Run 등 서비스별 집계 |
| 일별 트렌드 | 최근 30일 비용 추이 그래프 |
| SKU 상세 | Gemini API 모델별 사용량 및 비용 |
| 월별 요약 | 월간 비용 요약 및 서비스 분포 |
| 환율 적용 | USD → KRW 자동 환산 (1,350원 기준) |
API 엔드포인트:
| 엔드포인트 | 설명 |
|---|---|
GET /api/admin/billing/dashboard |
빌링 대시보드 데이터 |
GET /api/admin/billing/status |
빌링 데이터 사용 가능 여부 |
📊 API 사용량 추적 (v3.2.0 신규)
모든 외부 API 호출을 추적하여 비용 분석 및 과금 대비 데이터를 제공합니다.
추적 대상:
| 서비스 | 추적 항목 |
|---|---|
| Gemini | 모델명, 입/출력 토큰, 이미지 수, 지연시간 |
| Suno | 오디오 길이, 장르, 생성 시간 |
| YouTube | 업로드 영상 수, 용량 |
| TikTok | 업로드 수, 상태 |
데이터베이스 스키마:
CREATE TABLE api_usage_logs (
id INTEGER PRIMARY KEY,
service TEXT NOT NULL, -- 'gemini', 'suno', 'youtube'
model TEXT, -- 'gemini-2.0-flash', etc.
endpoint TEXT, -- API 엔드포인트
user_id INTEGER, -- 사용자 ID (과금용)
tokens_input INTEGER, -- 입력 토큰
tokens_output INTEGER, -- 출력 토큰
image_count INTEGER, -- 이미지 수
audio_seconds REAL, -- 오디오 길이
status TEXT, -- 'success', 'error'
error_message TEXT,
latency_ms INTEGER, -- 응답 시간
cost_estimate REAL, -- 예상 비용 (USD)
createdAt DATETIME
);
관리자 대시보드:
- 총 API 호출 수 / 예상 비용
- 서비스별/모델별 사용량 분포
- 사용자별 사용량 랭킹 (과금 대비)
- 최근 오류 로그
- 월별 리포트 자동 생성
🎯 AI 모델 우선순위 시스템 (v3.2.0 신규)
API 오류 시 자동으로 대체 모델로 전환하는 지능적 Fallback 시스템입니다.
이미지 생성 모델 우선순위:
| 순위 | 모델 | 예상 비용 | 최대 재시도 |
|---|---|---|---|
| 1 | gemini-2.0-flash-preview-image-generation | $0.02/이미지 | 2회 |
| 2 | gemini-2.5-flash-image | $0.015/이미지 | 2회 |
| 3 | imagen-3.0-generate-002 | $0.03/이미지 | 1회 |
Fallback 트리거:
- HTTP 429 (Rate Limit Exceeded)
- HTTP 500 (Internal Server Error)
- 타임아웃 (30초 초과)
로깅:
모든 모델 전환 시도는 api_usage_logs 테이블에 기록되어 추후 분석에 활용됩니다.
✨ AI 매직 라이트 (v3.2.0 신규)
펜션 정보를 기반으로 매력적인 마케팅 컨셉 설명을 자동 생성합니다.
입력 데이터:
- 펜션 이름
- 주소/지역
- 펜션 카테고리 (풀빌라, 오션뷰 등)
- 선택된 축제 정보
- 기존 설명 (참고용)
출력: 2-3문장의 감성적이고 매력적인 마케팅 컨셉 설명
사용 방법:
- 펜션 기본 정보 입력
- 카테고리 선택
- 근처 축제 선택 (선택사항)
- "AI 매직 라이트" 버튼 클릭
- 자동 생성된 컨셉 확인/수정
API:
POST /api/ai/auto-description
Body: { name, address, pensionCategories, selectedFestivals, existingDescription }
Response: { description, success }
🔐 개별 YouTube 연동 (v3.2.0 개선)
각 사용자가 자신의 YouTube 채널을 연결하여 직접 업로드할 수 있습니다.
OAuth 2.0 플로우:
1. 사용자: "YouTube 연결" 클릭
2. → Google OAuth 페이지로 리다이렉트
3. 사용자: Google 계정 로그인 + 권한 승인
4. → 콜백 URL로 인증 코드 반환
5. 서버: 인증 코드 → 액세스 토큰 교환
6. 서버: 토큰을 사용자 DB에 저장
7. 이후 업로드 시 저장된 토큰 사용
설정 요구사항 (개발자):
- Google Cloud Console에서 OAuth 2.0 클라이언트 생성
- YouTube Data API v3 활성화
- 승인된 리디렉션 URI 등록:
http://localhost:3001/api/youtube/oauth/callback(개발)https://castad1.ktenterprise.net/api/youtube/oauth/callback(프로덕션)
사용자 경험:
- 설정 페이지에서 "YouTube 연결" 버튼 클릭
- Google 계정으로 로그인 및 권한 승인
- 연결 완료 후 자신의 채널에 직접 업로드 가능
API 엔드포인트:
| 엔드포인트 | 설명 |
|---|---|
GET /api/youtube/oauth/url |
OAuth 인증 URL 생성 |
GET /api/youtube/oauth/callback |
OAuth 콜백 처리 |
GET /api/youtube/connection |
연결 상태 확인 |
POST /api/youtube/my-upload |
사용자 채널에 업로드 |
Part A. 개발자 매뉴얼 (Developer Manual)
이 섹션은 CaStAD의 코드를 이해하고 수정하거나 기여하려는 개발자를 위한 기술 문서입니다.
A1. 시스템 아키텍처
시스템 아키텍처 다이어그램
SVG 다이어그램 보기: public/images/architecture-diagram.svg
계층별 구조
1. 클라이언트 계층 (Frontend)
| 컴포넌트 | 설명 |
|---|---|
| Landing Page | 마케팅 홈페이지, 기능 소개 |
| CastAD App | 메인 SPA 애플리케이션 |
| Admin Dashboard | 관리자 전용 대시보드 |
| React Router v7 | SPA 라우팅 관리 |
| Context API | Auth, Language, Theme, UserLevel 전역 상태 |
2. 서버 계층 (Backend)
| 모듈 | 역할 |
|---|---|
| Auth Routes | 인증/인가 (JWT, OAuth 2.0) |
| Pension Routes | 펜션 CRUD, 이미지 관리 |
| YouTube Routes | OAuth, 업로드, 플레이리스트 |
| TikTok Routes | OAuth, Direct Post, Inbox 업로드 |
| Instagram Routes | 계정 연결, Reels 업로드 |
| Gemini Routes | AI 콘텐츠 생성 프록시 |
| Crawling Routes | 네이버/구글/인스타그램 크롤링 |
| Render Engine | Puppeteer + FFmpeg 영상 생성 |
3. 데이터 계층
| 컴포넌트 | 용도 |
|---|---|
| SQLite | 메타데이터, 사용자, 설정 저장 |
| Puppeteer | 헤드리스 브라우저 렌더링 |
| FFmpeg | 오디오/비디오 병합 |
| FileSystem | 생성된 MP4, 이미지 저장 |
4. 외부 API
| API | 용도 |
|---|---|
| Google Gemini | 광고 카피, TTS, 이미지 생성 |
| Suno AI | AI 음악 생성 |
| YouTube Data API | 영상 업로드, 플레이리스트 |
| TikTok API | TikTok 영상 게시 |
| Instagram API | Reels 업로드 (Python 마이크로서비스) |
| Tour API | 한국관광공사 축제 데이터 |
| Kakao Maps API | 지오코딩 |
영상 생성 파이프라인
┌─────────────────────────────────────────────────────────────────────────────┐
│ 1. INPUT │
│ 펜션 정보 입력 → 네이버/구글/인스타 크롤링 → 이미지 15장 선택 │
└─────────────────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ 2. AI GENERATION │
│ 광고 카피 (Gemini) │ 음악 (Suno AI) │ 포스터 (Imagen 3) │ TTS (Gemini) │
└─────────────────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ 3. RENDERING │
│ HTML/CSS 애니메이션 → Puppeteer 캡처 → FFmpeg 오디오 병합 │
└─────────────────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ 4. POST-PROCESSING │
│ 해상도 최적화 │ 메타데이터 추출 │ 썸네일 생성 │
└─────────────────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ 5. UPLOAD │
│ YouTube (OAuth) │ TikTok (OAuth) │ Instagram (Reels) │
└─────────────────────────────────────────────────────────────────────────────┘
데이터 흐름 다이어그램
flowchart TD
A[📝 사용자 입력] --> B[🗺️ 네이버/구글/인스타 크롤링]
B --> C[🤖 AI 콘텐츠 생성]
C --> C1[광고 카피 - Gemini 2.5 Flash]
C --> C2[음악 생성 - Suno AI v5]
C --> C3[포스터 생성 - Imagen 3]
C --> C4[음성 합성 - Gemini TTS]
C1 & C2 & C3 & C4 --> D[🎬 영상 렌더링]
D --> D1[HTML/CSS 애니메이션]
D --> D2[Puppeteer 화면 캡처]
D --> D3[FFmpeg 오디오 병합]
D1 & D2 & D3 --> E[💾 결과물 저장]
E --> E1[(SQLite - 메타데이터)]
E --> E2[📁 FileSystem - MP4]
E --> F[📺 멀티 플랫폼 업로드]
F -->|OAuth 2.0| F1[YouTube]
F -->|OAuth 2.0| F2[TikTok]
F -->|API| F3[Instagram Reels]
A2. 기술 스택
Frontend
| 카테고리 | 기술 | 버전 | 용도 |
|---|---|---|---|
| Core | React | 19.x | UI 프레임워크 |
| Language | TypeScript | 5.x | 타입 안전성 |
| Build | Vite | 6.x | 빌드 도구 |
| Routing | React Router | 7.x | SPA 라우팅 |
| Styling | Tailwind CSS | 3.x | 유틸리티 CSS |
| UI Components | shadcn/ui | latest | Radix 기반 컴포넌트 |
| Icons | Lucide React | latest | 아이콘 라이브러리 |
| State | Context API | - | 전역 상태 관리 |
Backend
| 카테고리 | 기술 | 버전 | 용도 |
|---|---|---|---|
| Runtime | Node.js | 22.x | 서버 런타임 |
| Framework | Express.js | 4.x | HTTP 서버 |
| Database | SQLite3 | 5.x | 경량 RDBMS |
| Auth | JWT | - | 토큰 기반 인증 |
| Crypto | Bcrypt | 5.x | 비밀번호 해싱 |
| Rendering | Puppeteer | 23.x | 헤드리스 브라우저 |
| Media | FFmpeg | 7.x | 영상/음성 처리 |
| Upload | Multer | 1.x | 파일 업로드 |
| OAuth | Google APIs | - | YouTube 연동 |
External Services
| 서비스 | 용도 | API |
|---|---|---|
| Google Gemini | 텍스트/이미지 생성, TTS | REST API |
| Suno AI | 음악 생성 | Proxy API |
| YouTube | 영상 업로드, 채널 관리 | Data API v3 |
| TikTok | 영상 업로드, 계정 연동 | Content Posting API |
| 영상 업로드 | Basic Display API | |
| Naver Maps | 업체 정보 크롤링 | Web Scraping |
| Google Maps | 업체 정보 크롤링 | Web Scraping |
A3. 프로젝트 구조
디렉토리 구조
19-claude-festival-castad/
├── 📁 components/ # 공통 React 컴포넌트
│ ├── InputForm.tsx # 영상 생성 입력 폼
│ ├── LoadingOverlay.tsx # 로딩 화면
│ ├── Navbar.tsx # 상단 네비게이션
│ ├── ResultPlayer.tsx # 결과 영상 플레이어
│ ├── DNACard.tsx # 펜션 DNA 분석 카드
│ ├── KoreaMap.tsx # 한국 지도 시각화
│ ├── OnboardingDialog.tsx # 사용자 온보딩
│ ├── PensionOnboardingDialog.tsx # 펜션 등록 다이얼로그
│ ├── YouTubeSEOPreview.tsx # YouTube SEO 프리뷰
│ └── ui/ # shadcn/ui 컴포넌트 (30+)
│
├── 📁 src/
│ ├── 📁 components/ # 앱 전용 컴포넌트
│ │ ├── layout/ # 레이아웃 컴포넌트
│ │ │ ├── Sidebar.tsx # 사이드 네비게이션
│ │ │ ├── TopHeader.tsx# 상단 헤더
│ │ │ └── SidebarItem.tsx # 사이드바 메뉴 항목
│ │ └── wizard/ # 마법사 컴포넌트
│ │ └── StepIndicator.tsx # 단계 표시기
│ │
│ ├── 📁 contexts/ # React Context (전역 상태)
│ │ ├── AuthContext.tsx # JWT 인증 상태
│ │ ├── LanguageContext.tsx # 다국어 (6개국)
│ │ ├── ThemeContext.tsx # 다크/라이트 모드 + 컬러 팔레트
│ │ └── UserLevelContext.tsx # 사용자 레벨 (Beginner/Pro)
│ │
│ ├── 📁 pages/ # 페이지 컴포넌트 (12개)
│ │ ├── GeneratorPage.tsx # 레거시 영상 생성 페이지
│ │ ├── Dashboard.tsx # 레거시 대시보드
│ │ ├── CastADApp.tsx # 메인 SPA 레이아웃
│ │ ├── AdminDashboard.tsx # 관리자 대시보드 (6000+ lines)
│ │ ├── LandingPage.tsx # 마케팅 랜딩
│ │ ├── BrandPage.tsx # 브랜드 소개
│ │ ├── LoginPage.tsx # 로그인
│ │ ├── RegisterPage.tsx # 회원가입
│ │ ├── CreditsPage.tsx # 크레딧 관리
│ │ ├── OAuthCallbackPage.tsx # OAuth 콜백
│ │ ├── ForgotPasswordPage.tsx # 비밀번호 찾기
│ │ └── VerifyEmailPage.tsx # 이메일 인증
│ │
│ ├── 📁 views/ # 앱 내 뷰 컴포넌트 (8개)
│ │ ├── DashboardView.tsx # 대시보드 (19.8KB)
│ │ ├── NewProjectView.tsx # 새 영상 생성 마법사 (112KB, 가장 복잡)
│ │ ├── LibraryView.tsx # 영상 라이브러리 (14.5KB)
│ │ ├── PensionsView.tsx # 펜션 프로필 관리 (51.5KB)
│ │ ├── FestivalsView.tsx # 축제 정보 (26.4KB)
│ │ ├── AssetsView.tsx # 에셋 관리 (24.8KB)
│ │ ├── SettingsView.tsx # 설정 (57.9KB)
│ │ └── AccountView.tsx # 계정 정보 (16.2KB)
│ │
│ ├── 📁 styles/ # 스타일시트
│ │ └── globals.css # 전역 CSS
│ │
│ └── locales.ts # 다국어 번역 (KO/EN/JA/ZH/TH/VI)
│
├── 📁 services/ # 프론트엔드 API 서비스 (7개)
│ ├── geminiService.ts # Gemini AI API (텍스트/이미지/TTS)
│ ├── sunoService.ts # Suno AI 음악 생성
│ ├── naverService.ts # 네이버 플레이스 크롤링
│ ├── googlePlacesService.ts # Google Places 크롤링
│ ├── instagramService.ts # Instagram 프로필 크롤링 (v3.6.0)
│ ├── ffmpegService.ts # FFmpeg WASM (클라이언트)
│ └── audioUtils.ts # 오디오 유틸리티
│
├── 📁 server/ # 백엔드 서버
│ ├── index.js # Express 메인 (7200+ lines, 150+ API)
│ ├── db.js # SQLite 스키마 (850+ lines, 30+ 테이블)
│ ├── geminiBackendService.js # Gemini 백엔드 프록시
│ ├── youtubeService.js # YouTube Data API v3
│ ├── tiktokService.js # TikTok API 서비스
│ ├── statisticsService.js # 고급 통계 분석
│ ├── 📁 instagram-service/ # Instagram 마이크로서비스 (Python)
│ │ ├── instagram_service.py
│ │ └── requirements.txt
│ ├── 📁 downloads/ # 생성된 영상 저장
│ ├── 📁 temp/ # 임시 렌더링 파일
│ └── 📁 user_assets/ # 사용자 업로드 파일
│
├── 📁 public/ # 정적 파일
│ └── images/
│ ├── castad-logo.svg
│ └── architecture-diagram.svg
│
├── App.tsx # React 앱 루트
├── types.ts # TypeScript 타입 정의
├── vite.config.ts # Vite 설정 (프록시 포함)
├── tailwind.config.js # Tailwind 설정
├── package.json # 프론트엔드 의존성
├── start.sh # 통합 실행 스크립트
├── test_api.sh # API 테스트 스크립트
├── CLAUDE.md # Claude Code 가이드
└── .env # 환경 변수 (Git 제외)
Context API 상세
| Context | Hook | 제공 기능 |
|---|---|---|
| AuthContext | useAuth() |
user, token, login, logout, isAdmin |
| LanguageContext | useLanguage() |
language, setLanguage, t(key) |
| ThemeContext | useTheme() |
theme, palette, setTheme, toggleTheme |
| UserLevelContext | useUserLevel() |
level, setLevel, features, isLoading |
프론트엔드 서비스 레이어
| 서비스 | 주요 함수 | 용도 |
|---|---|---|
| geminiService | generateCreativeContent(), synthesizeSpeech(), generateAdPoster(), filterImages() | Gemini API 호출 |
| sunoService | generateMusic(), cleanLyricsForSuno() | AI 음악 생성 |
| naverService | crawlNaverPlace(), parseNaverPlaceUrl() | 네이버 지도 크롤링 |
| googlePlacesService | searchPlace(), getPlaceDetails(), getPlacePhoto() | Google Places 크롤링 |
| instagramService | crawlInstagramProfile(), parseInstagramUrl() | 인스타그램 크롤링 |
| ffmpegService | mergeVideoWithAudio(), initFFmpeg() | 클라이언트 비디오 처리 |
| audioUtils | decodeBase64Audio(), arrayBufferToWav() | 오디오 유틸리티 |
라우팅 구조
/ (root)
├── /login → LoginPage
├── /register → RegisterPage
├── /forgot-password → ForgotPasswordPage
├── /verify-email → VerifyEmailPage
├── /reset-password → ResetPasswordPage
├── /oauth/callback → OAuthCallbackPage
├── /landing → LandingPage
├── /brand → BrandPage
├── /credits → CreditsPage (인증 필요)
├── /admin → AdminDashboard (관리자 전용)
└── /app → CastADApp (인증 필요)
├── ?view=dashboard → DashboardView
├── ?view=new-project → NewProjectView
├── ?view=library → LibraryView
├── ?view=pensions → PensionsView
├── ?view=festivals → FestivalsView
├── ?view=assets → AssetsView
├── ?view=settings → SettingsView
└── ?view=account → AccountView
A4. 데이터베이스 스키마
SQLite 데이터베이스 파일:
server/database.sqlite
테이블 카테고리별 구성 (총 30+ 테이블)
1. 사용자 및 인증 (User & Auth)
| 테이블 | 설명 | 주요 컬럼 |
|---|---|---|
users |
사용자 계정, 플랜, 크레딧 | id, username, email, password, role, plan_type, credits, max_pensions, experience_level |
credit_requests |
크레딧 충전 요청 | user_id, requested_credits, status, reason, processed_by |
credit_history |
크레딧 변동 이력 | user_id, amount, type, description, balance_after |
activity_logs |
시스템 활동 로그 | user_id, action_type, ip_address, metadata |
2. 펜션 관리 (Pension Management)
| 테이블 | 설명 | 주요 컬럼 |
|---|---|---|
pension_profiles |
펜션/숙소 프로필 (다중 지원) | user_id, brand_name, region, address, youtube_playlist_id, mapx, mapy |
pension_images |
펜션 이미지 보관함 | pension_id, filename, source(naver/google/instagram/upload), is_priority |
daily_auto_generation |
일일 자동 생성 설정 | pension_id, enabled, generation_time, image_mode, auto_upload_youtube/instagram/tiktok |
auto_generation_logs |
자동 생성 로그 | pension_id, status, youtube_video_id, instagram_media_id, tiktok_video_id |
3. 영상 및 에셋 (Video & Assets)
| 테이블 | 설명 | 주요 컬럼 |
|---|---|---|
history |
생성된 영상 히스토리 | user_id, pension_id, business_name, details(JSON), final_video_path, poster_path |
user_assets |
사용자 에셋 (이미지/오디오/비디오) | user_id, asset_type, source_type, file_path, file_size, duration |
generation_queue |
자동 생성 작업 큐 | user_id, pension_id, status, scheduled_at, result_video_path |
4. YouTube 연동
| 테이블 | 설명 | 주요 컬럼 |
|---|---|---|
youtube_connections |
YouTube OAuth 토큰 | user_id, google_email, youtube_channel_id, access_token, refresh_token |
youtube_settings |
업로드 기본 설정 | user_id, default_privacy, default_category_id, auto_upload |
youtube_playlists |
플레이리스트 캐시 | user_id, pension_id, playlist_id, title, item_count |
upload_history |
YouTube 업로드 기록 | user_id, pension_id, youtube_video_id, youtube_url, status |
youtube_analytics |
YouTube 분석 데이터 캐시 | pension_id, playlist_id, date, views, likes, subscribers_gained |
pension_monthly_stats |
월간 통계 요약 | pension_id, year_month, total_views, total_videos, growth_rate |
5. Instagram 연동
| 테이블 | 설명 | 주요 컬럼 |
|---|---|---|
instagram_connections |
Instagram 계정 연결 | user_id, instagram_username, encrypted_password, encrypted_session |
instagram_settings |
Instagram 업로드 설정 | user_id, auto_upload, upload_as_reel, default_hashtags |
instagram_upload_history |
Instagram 업로드 기록 | user_id, pension_id, instagram_media_id, permalink, upload_type |
6. TikTok 연동
| 테이블 | 설명 | 주요 컬럼 |
|---|---|---|
tiktok_connections |
TikTok OAuth 연결 | user_id, open_id, display_name, access_token, refresh_token |
tiktok_settings |
TikTok 업로드 설정 | user_id, default_privacy, disable_duet, auto_upload |
tiktok_upload_history |
TikTok 업로드 기록 | user_id, pension_id, video_id, privacy_level, status |
7. 외부 데이터 (TourAPI 연동)
| 테이블 | 설명 | 주요 컬럼 |
|---|---|---|
festivals |
전국 축제 정보 | content_id, title, addr1, event_start_date, event_end_date, mapx, mapy |
public_pensions |
전국 펜션 마스터 데이터 | name, address, sido, sigungu, mapx, mapy, facilities, pet_allowed |
pension_festival_matches |
펜션-축제 매칭 | pension_id, festival_id, distance_km, match_score |
area_codes |
지역 코드 (17개 시도) | code, name, name_short, name_en |
8. 시스템 관리
| 테이블 | 설명 | 주요 컬럼 |
|---|---|---|
system_settings |
시스템 설정 (쿠키 등) | setting_key, setting_value, is_encrypted, updated_by |
system_stats_daily |
일별 시스템 통계 | date, total_users, new_users, total_videos_generated |
api_usage_logs |
API 사용량 로그 | service, model, user_id, tokens_input, tokens_output, cost_estimate |
api_usage_daily |
API 일별 집계 | date, service, model, total_calls, total_cost_estimate |
platform_stats |
플랫폼 통합 통계 | user_id, platform, date, views, likes, engagement_rate |
ERD (Entity Relationship Diagram)
erDiagram
USERS ||--o{ PENSION_PROFILES : "owns"
USERS ||--o| YOUTUBE_CONNECTIONS : "has"
USERS ||--o| INSTAGRAM_CONNECTIONS : "has"
USERS ||--o| TIKTOK_CONNECTIONS : "has"
USERS ||--o{ HISTORY : "creates"
USERS ||--o{ USER_ASSETS : "owns"
USERS ||--o{ CREDIT_HISTORY : "has"
USERS ||--o{ API_USAGE_LOGS : "generates"
PENSION_PROFILES ||--o{ PENSION_IMAGES : "contains"
PENSION_PROFILES ||--o{ DAILY_AUTO_GENERATION : "has"
PENSION_PROFILES ||--o{ YOUTUBE_PLAYLISTS : "has"
PENSION_PROFILES ||--o{ AUTO_GENERATION_LOGS : "logs"
PENSION_PROFILES ||--o{ PENSION_FESTIVAL_MATCHES : "matches"
HISTORY ||--o{ UPLOAD_HISTORY : "youtube"
HISTORY ||--o{ INSTAGRAM_UPLOAD_HISTORY : "instagram"
HISTORY ||--o{ TIKTOK_UPLOAD_HISTORY : "tiktok"
FESTIVALS ||--o{ PENSION_FESTIVAL_MATCHES : "matched_to"
USERS {
int id PK
string username UK
string email UK
string password
string role
string plan_type
int credits
int max_pensions
string experience_level
}
PENSION_PROFILES {
int id PK
int user_id FK
string brand_name
string region
string address
real mapx
real mapy
}
PENSION_IMAGES {
int id PK
int pension_id FK
string filename
string source
int is_priority
}
HISTORY {
int id PK
int user_id FK
int pension_id FK
string business_name
string final_video_path
}
YOUTUBE_CONNECTIONS {
int id PK
int user_id FK UK
string youtube_channel_id
string access_token
string refresh_token
}
INSTAGRAM_CONNECTIONS {
int id PK
int user_id FK UK
string instagram_username
string encrypted_session
}
TIKTOK_CONNECTIONS {
int id PK
int user_id FK UK
string open_id
string access_token
}
FESTIVALS {
int id PK
string content_id UK
string title
string event_start_date
string event_end_date
}
인덱스 목록
-- 축제 검색 최적화
CREATE INDEX idx_festivals_area ON festivals(area_code, sigungu_code);
CREATE INDEX idx_festivals_date ON festivals(event_start_date, event_end_date);
CREATE INDEX idx_festivals_coords ON festivals(mapx, mapy);
-- 펜션 검색 최적화
CREATE INDEX idx_public_pensions_sido ON public_pensions(sido);
CREATE INDEX idx_public_pensions_sigungu ON public_pensions(sido, sigungu);
CREATE INDEX idx_public_pensions_coords ON public_pensions(mapx, mapy);
-- API 사용량 조회 최적화
CREATE INDEX idx_api_usage_service ON api_usage_logs(service, createdAt);
CREATE INDEX idx_api_usage_user ON api_usage_logs(user_id, createdAt);
CREATE INDEX idx_api_usage_date ON api_usage_logs(createdAt);
-- 펜션-축제 매칭 최적화
CREATE INDEX idx_matches_pension ON pension_festival_matches(pension_id, pension_type);
CREATE INDEX idx_matches_festival ON pension_festival_matches(festival_id);
A5. API 명세
총 150+ API 엔드포인트 Auth: ✅ = JWT 필요, 🔐 = Admin 필요, - = 공개
1. 인증 API (/api/auth/*)
| Method | Endpoint | 설명 | Auth | Body/Query |
|---|---|---|---|---|
| POST | /api/auth/register |
회원가입 | - | {username, email, password, name, phone} |
| POST | /api/auth/login |
JWT 로그인 | - | {username, password} |
| GET | /api/auth/me |
현재 사용자 정보 | ✅ | - |
| PUT | /api/auth/profile |
프로필 수정 | ✅ | {name, phone} |
| PUT | /api/auth/change-password |
비밀번호 변경 | ✅ | {currentPassword, newPassword} |
| GET | /api/auth/verify-email |
이메일 인증 | - | ?token=xxx |
| POST | /api/auth/resend-verification |
인증메일 재발송 | - | {email} |
| POST | /api/auth/forgot-password |
비밀번호 재설정 요청 | - | {email} |
| POST | /api/auth/reset-password |
비밀번호 재설정 | - | {token, newPassword} |
| GET | /api/auth/google |
Google OAuth 시작 | - | - |
| GET | /api/auth/google/callback |
Google OAuth 콜백 | - | ?code=xxx |
| GET | /api/auth/naver |
Naver OAuth 시작 | - | - |
| GET | /api/auth/naver/callback |
Naver OAuth 콜백 | - | ?code=xxx |
2. 사용자 설정 API (/api/user/*)
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/user/plan |
현재 플랜 정보 | ✅ |
| GET | /api/user/level |
사용자 레벨 조회 | ✅ |
| PUT | /api/user/level |
사용자 레벨 변경 | ✅ |
| GET | /api/user/auto-generation |
자동 생성 설정 조회 | ✅ |
| PUT | /api/user/auto-generation |
자동 생성 설정 수정 | ✅ |
| GET | /api/user/auto-upload-settings |
자동 업로드 설정 조회 | ✅ |
| PUT | /api/user/auto-upload-settings |
자동 업로드 설정 수정 | ✅ |
3. 펜션 프로필 API (/api/profile/pension/*)
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/profile/pensions |
내 펜션 목록 | ✅ |
| GET | /api/profile/pension |
기본 펜션 조회 | ✅ |
| GET | /api/profile/pension/:id |
펜션 상세 조회 | ✅ |
| POST | /api/profile/pension |
펜션 생성 | ✅ |
| PUT | /api/profile/pension/:id |
펜션 수정 | ✅ |
| DELETE | /api/profile/pension/:id |
펜션 삭제 | ✅ |
| POST | /api/profile/pension/:id/default |
기본 펜션 설정 | ✅ |
| GET | /api/profile/pension/:id/analytics |
펜션 분석 데이터 | ✅ |
| GET | /api/profile/pensions/analytics-summary |
전체 펜션 분석 요약 | ✅ |
4. 펜션 이미지 API (/api/profile/pension/:id/images/*) - v3.6.0 신규
| Method | Endpoint | 설명 | Auth | Query |
|---|---|---|---|---|
| GET | /api/profile/pension/:id/images |
이미지 목록 | ✅ | ?source=naver|google|instagram|upload |
| POST | /api/profile/pension/:id/images |
이미지 업로드 | ✅ | - |
| DELETE | /api/profile/pension/:id/images/:imageId |
이미지 삭제 | ✅ | - |
| GET | /api/profile/pension/:id/images/stats |
소스별 이미지 통계 | ✅ | - |
이미지 소스 구분:
naver- 네이버 지도에서 크롤링google- 구글 지도에서 크롤링instagram- 인스타그램에서 크롤링upload- 사용자 직접 업로드
5. 자동 생성/업로드 API
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/profile/pension/:id/auto-generation |
자동 생성 설정 | ✅ |
| POST | /api/profile/pension/:id/auto-generation |
자동 생성 설정 저장 | ✅ |
| GET | /api/profile/pension/:id/auto-generation/logs |
자동 생성 로그 | ✅ |
| POST | /api/profile/pension/:id/auto-generation/trigger |
수동 트리거 | ✅ |
| PATCH | /api/auto-generation/logs/:logId |
로그 상태 업데이트 | ✅ |
| GET | /api/auto-generation/scheduled |
예약된 작업 목록 | - |
| POST | /api/auto-upload |
자동 업로드 실행 | ✅ |
6. 렌더링 큐 API (/api/render/*) - v3.7.0 신규
백그라운드 렌더링 시스템: 페이지 이동/로그아웃해도 작업 계속 진행
| Method | Endpoint | 설명 | Auth | Body/Response |
|---|---|---|---|---|
| POST | /api/render/start |
렌더링 작업 시작 | ✅ | {posterBase64, audioBase64, imagesBase64, adCopy, textEffect, businessName, aspectRatio, pensionId} → {jobId, creditsCharged} |
| GET | /api/render/status/:jobId |
작업 상태 조회 | ✅ | → {status, progress, downloadUrl, error_message} |
| GET | /api/render/jobs |
내 작업 목록 | ✅ | ?status=pending&limit=20 → {jobs[], pendingCount} |
렌더링 흐름:
1. POST /api/render/start
└─ 크레딧 체크 → 선차감 → render_jobs 저장 → jobId 반환 (즉시)
2. Background Worker
└─ pending 작업 처리 (MAX 3개 동시)
└─ Puppeteer 녹화 + FFmpeg 합성
└─ 진행률 DB 업데이트
3. GET /api/render/status/:jobId (폴링)
└─ progress: 0-100%
└─ status: completed → downloadUrl 제공
└─ status: failed → credits_refunded (환불)
제한 사항:
| 제한 | 값 | 에러 코드 |
|---|---|---|
| 계정당 동시 렌더링 | 1개 | RENDER_IN_PROGRESS (429) |
| 서버 전체 동시 렌더링 | 3개 | 큐 대기 |
| 크레딧 부족 | - | INSUFFICIENT_CREDITS (403) |
7. 크롤링 API - v3.6.0 확장
네이버 지도 크롤링
| Method | Endpoint | 설명 | Auth | Body |
|---|---|---|---|---|
| POST | /api/naver/crawl |
네이버 플레이스 크롤링 | - | {url} |
인스타그램 크롤링 - v3.6.0 신규
| Method | Endpoint | 설명 | Auth | Body |
|---|---|---|---|---|
| POST | /api/instagram/crawl |
Instagram 프로필 크롤링 | - | {url} |
Google Places API
| Method | Endpoint | 설명 | Auth | Body |
|---|---|---|---|---|
| POST | /api/google/places/search |
장소 검색 | ✅ | {query} |
| POST | /api/google/places/details |
장소 상세 정보 | ✅ | {placeId} |
| POST | /api/google/places/photo |
사진 다운로드 | ✅ | {photoReference} |
7. AI API (Gemini / Suno)
Gemini AI 엔드포인트
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| POST | /api/gemini/creative-content |
광고 카피 생성 | ✅ |
| POST | /api/gemini/speech |
TTS 음성 합성 | ✅ |
| POST | /api/gemini/ad-poster |
광고 포스터 생성 (Imagen 3) | ✅ |
| POST | /api/gemini/image-gallery |
갤러리 이미지 생성 | ✅ |
| POST | /api/gemini/video-background |
비디오 배경 생성 | ✅ |
| POST | /api/gemini/text-effect |
텍스트 이펙트 생성 | ✅ |
| POST | /api/gemini/filter-images |
이미지 필터링/분류 | ✅ |
| POST | /api/gemini/enrich-description |
설명 보강 | ✅ |
| POST | /api/gemini/search-business |
비즈니스 정보 검색 | ✅ |
| POST | /api/gemini/analyze-dna |
펜션 DNA 분석 | ✅ |
Suno AI 음악 생성
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| POST | /api/suno/generate |
AI 음악 생성 | ✅ |
8. YouTube API (/api/youtube/*)
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/youtube/oauth/url |
OAuth URL 생성 | ✅ |
| GET | /api/youtube/oauth/callback |
OAuth 콜백 처리 | - |
| GET | /api/youtube/connection |
연결 상태 조회 | ✅ |
| DELETE | /api/youtube/connection |
연결 해제 | ✅ |
| GET | /api/youtube/settings |
업로드 설정 조회 | ✅ |
| POST | /api/youtube/settings |
업로드 설정 저장 | ✅ |
| GET | /api/youtube/my-playlists |
내 플레이리스트 | ✅ |
| POST | /api/youtube/my-playlists |
플레이리스트 생성 | ✅ |
| GET | /api/youtube/pension/:pensionId/playlists |
펜션별 플레이리스트 | ✅ |
| POST | /api/youtube/pension/:pensionId/playlists |
펜션 플레이리스트 연결 | ✅ |
| DELETE | /api/youtube/pension/:pensionId/playlists/:playlistId |
연결 해제 | ✅ |
| POST | /api/youtube/my-upload |
영상 업로드 | ✅ |
| POST | /api/youtube/upload |
영상 업로드 (레거시) | ✅ |
| GET | /api/youtube/upload-history |
업로드 히스토리 | ✅ |
| POST | /api/youtube/seo |
SEO 메타데이터 생성 | ✅ |
| GET | /api/youtube/playlists |
플레이리스트 목록 | ✅ |
| POST | /api/youtube/playlists |
플레이리스트 생성 | ✅ |
| GET | /api/youtube/playlists/:playlistId/videos |
플레이리스트 영상 | ✅ |
| POST | /api/youtube/playlists/business |
비즈니스 플레이리스트 | ✅ |
| POST | /api/profile/pension/:id/youtube-playlist |
펜션-플레이리스트 연결 | ✅ |
| DELETE | /api/profile/pension/:id/youtube-playlist |
연결 해제 | ✅ |
9. Instagram API (/api/instagram/*) - v3.0+ 신규
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/instagram/health |
서비스 상태 확인 | - |
| POST | /api/instagram/connect |
계정 연결 | ✅ |
| POST | /api/instagram/disconnect |
연결 해제 | ✅ |
| GET | /api/instagram/status |
연결 상태 조회 | ✅ |
| PUT | /api/instagram/settings |
업로드 설정 수정 | ✅ |
| POST | /api/instagram/upload |
Reels 업로드 | ✅ |
| GET | /api/instagram/weekly-stats |
주간 통계 | ✅ |
| GET | /api/instagram/history |
업로드 히스토리 | ✅ |
10. TikTok API (/api/tiktok/*) - v3.0 신규
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/tiktok/oauth/url |
OAuth URL 생성 | ✅ |
| GET | /api/tiktok/oauth/callback |
OAuth 콜백 처리 | - |
| GET | /api/tiktok/status |
연결 상태 조회 | ✅ |
| POST | /api/tiktok/disconnect |
연결 해제 | ✅ |
| GET | /api/tiktok/settings |
업로드 설정 조회 | ✅ |
| PUT | /api/tiktok/settings |
업로드 설정 수정 | ✅ |
| POST | /api/tiktok/upload |
Direct Post 업로드 | ✅ |
| POST | /api/tiktok/upload-to-inbox |
Draft/Inbox 업로드 | ✅ |
| GET | /api/tiktok/history |
업로드 히스토리 | ✅ |
| GET | /api/tiktok/stats |
통계 조회 | ✅ |
11. 에셋 API (/api/user-assets/*)
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/user-assets/stats |
스토리지 통계 | ✅ |
| GET | /api/user-assets |
에셋 목록 | ✅ |
| POST | /api/user-assets/upload |
파일 업로드 (다중) | ✅ |
| DELETE | /api/user-assets/:id |
에셋 삭제 | ✅ |
| POST | /api/assets/upload |
에셋 업로드 (일반) | ✅ |
12. 히스토리 API (/api/history/*)
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/history |
생성 기록 목록 | ✅ |
| POST | /api/history |
기록 저장 | ✅ |
| DELETE | /api/history/:id |
기록 삭제 | ✅ |
| DELETE | /api/history |
일괄 삭제 | ✅ |
13. 크레딧 API (/api/credits/*)
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/credits |
크레딧 잔액 조회 | ✅ |
| GET | /api/credits/history |
크레딧 사용 내역 | ✅ |
| POST | /api/credits/request |
충전 요청 | ✅ |
| GET | /api/credits/requests |
내 충전 요청 목록 | ✅ |
14. 축제/공개 펜션 API
축제 API (/api/festivals/*)
| Method | Endpoint | 설명 | Auth | Query |
|---|---|---|---|---|
| GET | /api/festivals |
축제 목록 | - | ?region=&month=&keyword= |
| GET | /api/festivals/grouped |
지역별 그룹화 | - | - |
| GET | /api/festivals/:id |
축제 상세 | - | - |
| GET | /api/festivals/:id/nearby-pensions |
근처 펜션 | - | - |
| GET | /api/festivals/stats/by-region |
지역별 통계 | - | - |
| GET | /api/festivals/stats/by-month |
월별 통계 | - | - |
공개 펜션 API (/api/pensions/*)
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/pensions |
공개 펜션 목록 | - |
| GET | /api/pensions/:id |
펜션 상세 | - |
| GET | /api/pensions/:id/nearby-festivals |
근처 축제 | - |
| GET | /api/pensions/stats/by-region |
지역별 통계 | - |
15. 관리자 API (/api/admin/*)
사용자 관리
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/admin/users |
사용자 목록 | 🔐 |
| GET | /api/admin/users/:id/detail |
사용자 상세 | 🔐 |
| POST | /api/admin/users |
사용자 생성 | 🔐 |
| DELETE | /api/admin/users/:id |
사용자 삭제 | 🔐 |
| POST | /api/admin/approve |
사용자 승인 | 🔐 |
| PUT | /api/admin/users/:id/role |
역할 변경 | 🔐 |
| PUT | /api/admin/users/:id/plan |
플랜 변경 | 🔐 |
| POST | /api/admin/users/:id/reset-password |
비밀번호 초기화 | 🔐 |
| POST | /api/admin/users/:id/credits |
크레딧 직접 조정 | 🔐 |
크레딧 관리
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/admin/credits/requests |
충전 요청 목록 | 🔐 |
| POST | /api/admin/credits/requests/:id/process |
요청 처리 | 🔐 |
| GET | /api/admin/credits/stats |
크레딧 통계 | 🔐 |
콘텐츠 관리
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/admin/history |
전체 생성 기록 | 🔐 |
| DELETE | /api/admin/history/:id |
기록 삭제 | 🔐 |
| DELETE | /api/admin/history |
기록 일괄 삭제 | 🔐 |
| GET | /api/admin/uploads |
업로드 현황 | 🔐 |
시스템 관리
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/admin/stats |
통계 요약 | 🔐 |
| GET | /api/admin/system-health |
시스템 상태 | 🔐 |
| GET | /api/admin/logs |
시스템 로그 | 🔐 |
| GET | /api/admin/settings |
설정 조회 | 🔐 |
| PUT | /api/admin/settings |
설정 수정 | 🔐 |
쿠키 관리 - v3.6.0 신규
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/admin/cookies |
쿠키 설정 조회 | 🔐 |
| PUT | /api/admin/cookies |
쿠키 설정 수정 | 🔐 |
데이터 동기화
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| POST | /api/admin/sync/festivals |
축제 데이터 동기화 | 🔐 |
| POST | /api/admin/sync/pensions |
펜션 데이터 동기화 | 🔐 |
16. 고급 통계 API (/api/admin/analytics/*)
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/admin/analytics/summary |
전체 요약 | 🔐 |
| GET | /api/admin/analytics/user-growth |
사용자 성장 추이 | 🔐 |
| GET | /api/admin/analytics/video-trend |
영상 생성 트렌드 | 🔐 |
| GET | /api/admin/analytics/platform-uploads |
플랫폼별 업로드 | 🔐 |
| GET | /api/admin/analytics/credit-usage |
크레딧 사용 분석 | 🔐 |
| GET | /api/admin/analytics/plan-distribution |
플랜 분포 | 🔐 |
| GET | /api/admin/analytics/top-users |
Top 활동 사용자 | 🔐 |
| GET | /api/admin/analytics/usage-pattern |
사용 패턴 분석 | 🔐 |
| GET | /api/admin/analytics/regional |
지역별 분포 | 🔐 |
| GET | /api/admin/analytics/revenue |
수익 예측 | 🔐 |
| GET | /api/admin/analytics/activity-logs |
활동 로그 | 🔐 |
| GET | /api/admin/analytics/system-health |
시스템 헬스 | 🔐 |
| POST | /api/admin/analytics/update-daily |
일일 통계 갱신 | 🔐 |
| GET | /api/admin/analytics/full-report |
전체 리포트 | 🔐 |
17. API 사용량/빌링 API
API 사용량 (/api/admin/api-usage/*)
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/admin/api-usage/stats |
사용량 통계 | 🔐 |
| GET | /api/admin/api-usage/logs |
사용 로그 | 🔐 |
| GET | /api/admin/api-usage/models |
모델별 사용량 | 🔐 |
| GET | /api/admin/api-usage/by-user |
사용자별 사용량 | 🔐 |
| GET | /api/admin/api-usage/user/:userId |
특정 사용자 상세 | 🔐 |
| GET | /api/admin/api-usage/monthly-report |
월간 리포트 | 🔐 |
빌링 (/api/admin/billing/*)
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/admin/billing/status |
빌링 상태 | 🔐 |
| GET | /api/admin/billing/dashboard |
빌링 대시보드 | 🔐 |
| GET | /api/admin/billing/by-service |
서비스별 비용 | 🔐 |
| GET | /api/admin/billing/daily |
일별 비용 | 🔐 |
| GET | /api/admin/billing/by-sku |
SKU별 비용 | 🔐 |
| GET | /api/admin/billing/monthly |
월별 비용 | 🔐 |
| GET | /api/admin/billing/gemini |
Gemini API 비용 | 🔐 |
18. 유틸리티 API
AI 보조
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| POST | /api/ai/auto-description |
자동 설명 생성 | ✅ |
프록시
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| GET | /api/proxy/image |
이미지 프록시 | - |
| GET | /api/proxy/audio |
오디오 프록시 | - |
렌더링
| Method | Endpoint | 설명 | Auth |
|---|---|---|---|
| POST | /render |
영상 렌더링 시작 | ✅ |
A6. 인증 시스템
JWT 토큰 구조
// 토큰 페이로드
{
"id": 1,
"username": "user@example.com",
"role": "user",
"iat": 1733400000,
"exp": 1733486400 // 24시간 후 만료
}
인증 미들웨어
// server/index.js
const authenticateToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) return res.status(401).json({ error: '인증 필요' });
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) return res.status(403).json({ error: '토큰 무효' });
req.user = user;
next();
});
};
const requireAdmin = (req, res, next) => {
if (req.user.role !== 'admin') {
return res.status(403).json({ error: '관리자 권한 필요' });
}
next();
};
OAuth 2.0 플로우
sequenceDiagram
participant C as Client
participant S as Server
participant G as Google/Naver
participant D as Database
C->>S: Click 소셜 로그인 버튼
S-->>C: Redirect to OAuth Provider
C->>G: User Login & Consent
G-->>C: Redirect with code
C->>S: /api/auth/{provider}/callback?code=xxx
S->>G: Exchange code for tokens
G-->>S: User profile (email, name, id)
alt 기존 사용자 (이메일 매칭)
S->>D: Link OAuth to existing account
else 신규 사용자
S->>D: Create new user with OAuth
end
S->>S: Generate JWT token
S-->>C: Redirect to /oauth/callback?token=xxx
A7. 영상 생성 파이프라인
전체 프로세스
flowchart TD
subgraph INPUT["1️⃣ INPUT"]
I1[펜션 정보]
I2[사진 업로드 - 최대 15장]
I3[지도 URL 크롤링]
end
subgraph AI["2️⃣ AI GENERATION"]
A1[광고 카피 - Gemini]
A2[음악 - Suno AI]
A3[포스터 - Imagen 3]
end
subgraph COMPOSE["3️⃣ COMPOSITION"]
C1[HTML/CSS 애니메이션]
C2[텍스트 이펙트]
C3[전환 효과]
end
subgraph RENDER["4️⃣ RENDER"]
R1[Puppeteer 캡처]
R2[FFmpeg 병합]
end
subgraph OUTPUT["5️⃣ OUTPUT"]
O1[MP4 다운로드]
O2[YouTube 업로드]
end
INPUT --> AI --> COMPOSE --> RENDER --> OUTPUT
텍스트 이펙트 종류
| 이펙트 | 설명 | CSS 클래스 |
|---|---|---|
| Neon | 네온 글로우 효과 | text-neon |
| Glitch | 글리치 효과 | text-glitch |
| Typewriter | 타자기 효과 | text-typewriter |
| Cinematic | 시네마틱 페이드 | text-cinematic |
| Bold | 볼드 팝업 | text-bold-pop |
| Motion | 모션 블러 | text-motion |
| LineReveal | 라인 공개 | text-line-reveal |
| Boxed | 박스 프레임 | text-boxed |
| Elegant | 엘레강트 | text-elegant |
| BlockReveal | 블록 공개 | text-block-reveal |
FFmpeg 명령어
# 이미지 시퀀스 → MP4
ffmpeg -framerate 30 -i frame_%04d.png \
-c:v libx264 -pix_fmt yuv420p \
-r 30 output_video.mp4
# 오디오 병합
ffmpeg -i output_video.mp4 -i audio.wav \
-c:v copy -c:a aac -shortest \
final_output.mp4
A8. 개발 환경 설정
1. 저장소 클론
git clone https://github.com/waabaa/19-claude-festival-castad.git
cd 19-claude-festival-castad
2. 의존성 설치
# Frontend
npm install
# Backend
cd server && npm install && cd ..
3. 환경 변수 설정
cp .env.example .env
# .env 파일 편집 (API 키 입력)
4. 개발 서버 실행
# 방법 1: 통합 스크립트
./start.sh
# 방법 2: npm 스크립트
npm run dev
# 방법 3: 개별 실행
npm run dev:frontend # Vite 프론트엔드
cd server && node index.js # Express 백엔드
5. 접속
- Frontend: http://localhost:3000
- Backend API: http://localhost:3001
- 기본 관리자: admin / admin123
A9. 코드 기여 가이드
브랜치 전략
main # 프로덕션 브랜치
├── develop # 개발 통합 브랜치
│ ├── feature/xxx # 기능 개발
│ ├── fix/xxx # 버그 수정
│ └── refactor/xxx # 리팩토링
커밋 메시지 컨벤션
feat: 새로운 기능 추가
fix: 버그 수정
docs: 문서 수정
style: 코드 포맷팅
refactor: 코드 리팩토링
test: 테스트 추가
chore: 빌드, 설정 변경
테스트 실행
# API 테스트
./test_api.sh
# 빌드 테스트
npm run build
Part B. 운용자 매뉴얼 (Operator Manual)
이 섹션은 CastAD Pro를 설치, 배포, 운영하는 시스템 관리자/운용자를 위한 가이드입니다.
B1. 시스템 요구사항
하드웨어 최소 사양
| 항목 | 최소 | 권장 |
|---|---|---|
| CPU | 2 Core | 4 Core |
| RAM | 4GB | 8GB |
| Storage | 20GB SSD | 100GB SSD |
| Network | 100Mbps | 1Gbps |
소프트웨어 요구사항
| 소프트웨어 | 최소 버전 | 확인 명령어 |
|---|---|---|
| Node.js | 18.x | node -v |
| npm | 9.x | npm -v |
| FFmpeg | 6.x | ffmpeg -version |
| Git | 2.x | git --version |
| Python 3 | 3.9+ | python3 --version |
운영체제 지원
| OS | 지원 여부 | 비고 |
|---|---|---|
| Ubuntu 20.04+ | ✅ 권장 | 프로덕션 권장 |
| Debian 11+ | ✅ 지원 | |
| CentOS 8+ | ✅ 지원 | |
| macOS 12+ | ✅ 지원 | 개발용 |
| Windows 10+ (WSL2) | ⚠️ 제한적 | WSL2 필수 |
B2. 설치 및 배포
방법 1: 직접 설치
# 1. 시스템 패키지 설치 (Ubuntu/Debian)
sudo apt update
sudo apt install -y nodejs npm ffmpeg git python3 python3-pip
# 2. Chrome/Chromium 설치 (Puppeteer용)
sudo apt install -y chromium-browser
# 3. 프로젝트 클론
git clone https://github.com/waabaa/19-claude-festival-castad.git
cd 19-claude-festival-castad
# 4. 의존성 설치
npm install
cd server && npm install && cd ..
# 5. 환경 변수 설정
cp .env.example .env
nano .env # API 키 입력
# 6. 프로덕션 빌드
npm run build
# 7. 실행
./start.sh
방법 2: PM2로 배포
# PM2 설치
npm install -g pm2
# 백엔드 실행
cd server
pm2 start index.js --name "castad-server"
# 프론트엔드 빌드 및 서빙
cd ..
npm run build
pm2 serve dist 3000 --name "castad-frontend" --spa
# 자동 재시작 설정
pm2 startup
pm2 save
방법 3: Nginx 리버스 프록시
# /etc/nginx/sites-available/castad
server {
listen 80;
server_name castad1.ktenterprise.net;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name castad1.ktenterprise.net;
ssl_certificate /etc/letsencrypt/live/castad1.ktenterprise.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/castad1.ktenterprise.net/privkey.pem;
# Frontend (정적 파일)
location / {
root /var/www/castad/dist;
try_files $uri $uri/ /index.html;
}
# Backend API
location /api {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_cache_bypass $http_upgrade;
}
# 렌더링 API
location /render {
proxy_pass http://localhost:3001;
proxy_read_timeout 300s; # 렌더링은 오래 걸릴 수 있음
}
# 다운로드 파일
location /downloads {
alias /var/www/castad/server/downloads;
}
}
B3. 환경 변수 설정
.env 파일 전체 구조
# ============================================
# Google AI API (필수)
# ============================================
VITE_GEMINI_API_KEY=AIzaSy...
# ============================================
# Suno AI Proxy (필수)
# ============================================
SUNO_API_KEY=suno_...
# ============================================
# 인증 (필수)
# ============================================
JWT_SECRET=your_super_secret_key_min_256_bits_random_string
# ============================================
# 서버 설정
# ============================================
PORT=3001
FRONTEND_URL=https://castad1.ktenterprise.net
# ============================================
# 이메일 서비스 (선택 - 이메일 인증용)
# ============================================
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password
SMTP_FROM=CastAD <noreply@castad.com>
# ============================================
# Google OAuth (선택 - 소셜 로그인용)
# ============================================
GOOGLE_CLIENT_ID=your_google_client_id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your_google_client_secret
# ============================================
# Naver OAuth (선택 - 소셜 로그인용)
# ============================================
NAVER_CLIENT_ID=your_naver_client_id
NAVER_CLIENT_SECRET=your_naver_client_secret
# ============================================
# Instagram 서비스 (선택)
# ============================================
INSTAGRAM_ENCRYPTION_KEY=base64_encoded_32_byte_key
환경 변수 설명
| 변수 | 필수 | 설명 |
|---|---|---|
VITE_GEMINI_API_KEY |
✅ | Google AI Studio에서 발급 |
SUNO_API_KEY |
✅ | Suno AI 프록시 API 키 |
JWT_SECRET |
✅ | 최소 256비트 랜덤 문자열 |
PORT |
❌ | 백엔드 포트 (기본: 3001) |
FRONTEND_URL |
❌ | CORS 허용 도메인 |
SMTP_* |
❌ | 이메일 인증 활성화 시 필요 |
GOOGLE_* |
❌ | Google 로그인/YouTube 연동 시 필요 |
NAVER_* |
❌ | Naver 로그인 시 필요 |
B4. 외부 서비스 연동
Google Cloud Console 설정
1. 프로젝트 생성
- https://console.cloud.google.com 접속
- 새 프로젝트 생성 또는 기존 프로젝트 선택
2. API 활성화
- YouTube Data API v3 활성화
- Gemini API (AI Studio에서 별도 발급)
3. OAuth 2.0 설정
-
API 및 서비스 → OAuth 동의 화면
- 사용자 유형: 외부
- 앱 이름: CastAD
- 범위(Scopes):
emailprofileopenidhttps://www.googleapis.com/auth/youtube.uploadhttps://www.googleapis.com/auth/youtube
-
사용자 인증 정보 → OAuth 2.0 클라이언트 ID 생성
- 애플리케이션 유형: 웹 애플리케이션
- 승인된 JavaScript 원본:
http://localhost:3000(개발)https://castad1.ktenterprise.net(프로덕션)
- 승인된 리디렉션 URI:
http://localhost:3001/api/auth/google/callbackhttp://localhost:3001/api/youtube/oauth/callbackhttps://api.castad1.ktenterprise.net/api/auth/google/callbackhttps://api.castad1.ktenterprise.net/api/youtube/oauth/callback
-
client_secret.json 다운로드
- 다운로드한 파일을
server/client_secret.json으로 저장
- 다운로드한 파일을
Naver Developers 설정
- https://developers.naver.com 접속
- 애플리케이션 등록
- 사용 API: 네아로 (네이버 아이디로 로그인)
- 필수 권한: 이름, 이메일, 프로필 사진
- 환경 추가: PC웹
- 서비스 URL:
https://castad1.ktenterprise.net - Callback URL:
https://api.castad1.ktenterprise.net/api/auth/naver/callback
- 서비스 URL:
- Client ID, Secret을
.env에 저장
TikTok for Developers 설정
1. 개발자 계정 등록
- https://developers.tiktok.com 접속
- 개발자 계정 등록 및 인증
2. 앱 생성
- My Apps → Create App
- 앱 유형: Web
- 앱 이름: CaStAD
3. Product 추가
- Login Kit: 사용자 인증
- Content Posting API: 영상 업로드
- Direct Post: 즉시 게시
- Inbox Upload: 초안으로 저장
4. OAuth 설정
- Scopes 설정:
user.info.basicuser.info.profileuser.info.statsvideo.publishvideo.upload
- Redirect URI:
http://localhost:3001/api/tiktok/oauth/callback(개발)https://api.castad1.ktenterprise.net/api/tiktok/oauth/callback(프로덕션)
5. 환경 변수 설정
TIKTOK_CLIENT_KEY=your_client_key
TIKTOK_CLIENT_SECRET=your_client_secret
6. TikTok 업로드 제한사항
| 항목 | 제한 |
|---|---|
| 영상 길이 | 3초 ~ 10분 |
| 파일 크기 | 최대 4GB |
| 해상도 | 720p 이상 권장 |
| 비율 | 9:16 (세로), 16:9 (가로), 1:1 (정사각형) |
| 일일 업로드 | 앱당 최대 100개 |
Instagram 연동 설정
1. 아키텍처 개요
Instagram은 공식 API 제약으로 인해 Python 마이크로서비스 방식을 사용합니다:
flowchart LR
A[CaStAD Server] -->|HTTP| B[Python Instagram Service]
B -->|Instagrapi| C[Instagram]
B -->|암호화| D[(SQLite)]
2. Python 서비스 설치
cd server/instagram
# 가상환경 생성 (권장)
python3 -m venv venv
source venv/bin/activate # Linux/Mac
# 또는 .\venv\Scripts\activate # Windows
# 의존성 설치
pip install instagrapi cryptography flask
3. 환경 변수 설정
# 암호화 키 생성 (최초 1회)
python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
# .env에 추가
INSTAGRAM_SERVICE_URL=http://localhost:5001
INSTAGRAM_ENCRYPTION_KEY=your_generated_key
4. 서비스 시작
cd server/instagram
python3 instagram_service.py
# → Flask 서버가 포트 5001에서 실행됨
5. Instagram 기능
| 기능 | 설명 |
|---|---|
| 계정 연결 | ID/PW로 로그인, 세션 암호화 저장 |
| 2FA 지원 | 2단계 인증 코드 입력 지원 |
| 릴스 업로드 | 최대 90초 세로 영상 |
| 주간 제한 | 안전한 사용을 위해 주당 1회 제한 (설정 가능) |
| 자동 재로그인 | 세션 만료 시 자동 갱신 |
6. Instagram 업로드 제한사항
| 항목 | 릴스 (Reels) |
|---|---|
| 영상 길이 | 3초 ~ 90초 |
| 파일 크기 | 최대 650MB |
| 해상도 | 1080x1920 권장 |
| 비율 | 9:16 (세로) |
| 주간 권장 | 1~3회 (계정 보호) |
7. 주의사항
⚠️ 중요: Instagram은 비공식 API를 사용하므로:
- 과도한 업로드는 계정 제재 위험이 있습니다
- 2FA 활성화를 권장합니다
- 주간 업로드 제한을 준수하세요
- 비즈니스 계정 사용을 권장합니다
Suno AI 설정
1. API 키 발급
- https://suno.ai 접속
- 계정 생성 및 구독
- API 키 발급
2. 환경 변수 설정
SUNO_API_KEY=your_suno_api_key
3. 음악 생성 옵션
| 옵션 | 설명 |
|---|---|
| 장르 | Pop, K-Pop, Jazz, Classical, EDM 등 |
| 분위기 | 밝은, 차분한, 신나는, 감성적인 등 |
| 길이 | 30초, 60초, 90초 |
| 보컬 | 포함/미포함 |
B5. 관리자 대시보드
접속 정보
- URL:
https://castad1.ktenterprise.net/admin - 초기 계정:
admin/admin123
⚠️ 중요: 첫 로그인 후 반드시 비밀번호를 변경하세요!
대시보드 메뉴 구성
| 메뉴 | 아이콘 | 기능 |
|---|---|---|
| 개요 | 📊 | 전체 통계, 최근 활동, 시스템 상태 |
| 회원 관리 | 👥 | 사용자 목록, 승인, 역할/플랜 변경 |
| 크레딧 | 💰 | 크레딧 요청 처리, 수동 조정 |
| 콘텐츠 | 🎬 | 생성된 영상 목록, 삭제 관리 |
| 업로드 현황 | 📤 | YouTube/TikTok/Instagram 업로드 통계 |
| 활동 로그 | 📋 | 사용자 활동 기록 |
| API 사용량 | 📈 | Gemini/Suno API 사용량 및 비용 |
| 설정 | ⚙️ | 시스템 설정, 쿠키 관리 (v3.6.0) |
개요 화면 정보
┌─────────────────────────────────────────────────────────┐
│ 전체 사용자: 150명 생성된 영상: 1,234개 │
│ 승인 대기: 5명 오늘 생성: 23개 │
│ 활성 사용자: 89명 YouTube 업로드: 567개 │
├─────────────────────────────────────────────────────────┤
│ 시스템 상태 │
│ ● Server: 정상 ● DB: 연결됨 ● Gemini: OK │
│ ● FFmpeg: 설치됨 ● Suno: OK ● YouTube: OK │
└─────────────────────────────────────────────────────────┘
B6. 사용자 관리
사용자 목록 조회
회원 관리 메뉴에서 모든 사용자를 확인할 수 있습니다:
| 컬럼 | 설명 |
|---|---|
| ID | 사용자 고유 ID |
| 아이디 | 로그인 아이디 |
| 이름 | 사용자 이름 |
| 플랜 | Free/Basic/Pro/Business |
| 크레딧 | 현재 보유 크레딧 |
| 역할 | user/admin |
| 상태 | 승인 대기/승인됨 |
| 가입일 | 가입 날짜 |
사용자 승인
신규 가입한 사용자는 기본적으로 승인 대기 상태입니다.
- 회원 관리 메뉴 이동
- 상태가 "대기"인 사용자 확인
- 승인 버튼 클릭
- 확인 대화상자에서 확인 클릭
역할 변경
사용자를 관리자로 승격하거나 강등할 수 있습니다.
- 회원 관리 메뉴에서 사용자 선택
- 역할 드롭다운에서 admin 또는 user 선택
- 변경사항 자동 저장
사용자 삭제
⚠️ 주의: 사용자 삭제 시 모든 관련 데이터(펜션, 영상, 에셋)가 삭제됩니다.
- 회원 관리 메뉴에서 사용자 선택
- 삭제 버튼 클릭
- 확인 메시지 입력 후 삭제 확인
B7. 플랜 및 크레딧 관리
플랜 종류
| 플랜 | 가격 (월) | 크레딧 | 펜션 수 | 스토리지 |
|---|---|---|---|---|
| Free | 무료 | 10 | 1개 | 500MB |
| Basic | ₩29,000 | 15 | 1개 | 2GB |
| Pro | ₩89,000 | 75 | 5개 | 10GB |
| Business | ₩249,000 | 무제한 | 무제한 | 50GB |
사용자 플랜 변경
- 회원 관리 메뉴 이동
- 변경할 사용자의 플랜 배지 클릭
- 플랜 수정 모달에서:
- 새 플랜 선택
- 크레딧 수량 조정 (선택)
- 저장 클릭
크레딧 수동 조정
- 크레딧 메뉴 → 사용자별 크레딧 현황
- 해당 사용자의 조정 버튼 클릭
- 조정량 입력:
- 양수: 크레딧 추가 (예:
+10) - 음수: 크레딧 차감 (예:
-5)
- 양수: 크레딧 추가 (예:
- 사유 입력
- 적용 클릭
크레딧 충전 요청 처리
- 크레딧 메뉴 → 충전 요청
- 대기 중인 요청 확인
- 각 요청에 대해:
- 승인: 요청된 크레딧 즉시 지급
- 거절: 요청 취소 (사유 입력 권장)
B8. 사진 관리 시스템
CaStAD는 다양한 소스에서 펜션 사진을 수집하고 관리할 수 있는 종합 사진 관리 시스템을 제공합니다.
지원 소스 (Image Sources)
| 소스 | 설명 | 설정 방법 |
|---|---|---|
| 네이버 지도 | 네이버 플레이스에서 사진 크롤링 | 네이버 쿠키 설정 (선택) |
| 구글 지도 | 구글 플레이스에서 사진 크롤링 | Google API 키 설정 |
| 인스타그램 | 인스타그램 프로필에서 사진 크롤링 | 인스타그램 쿠키 설정 (필수) |
| 직접 업로드 | 사용자가 직접 업로드한 사진 | - |
크롤링 사용법
-
펜션 등록 시 자동 크롤링:
- 네이버:
https://naver.me/...또는https://map.naver.com/... - 구글:
https://maps.google.com/...또는https://goo.gl/maps/... - 인스타:
https://instagram.com/username
- 네이버:
-
소스별 자동 분류:
- 크롤링된 이미지는 자동으로 소스가 구분되어 저장됩니다
- 파일명에 소스 접두사 포함:
naver_,google_,instagram_
쿠키 관리 (관리자)
관리자 대시보드 → 설정 → API 쿠키 관리
┌─────────────────────────────────────────┐
│ API 쿠키 관리 │
├─────────────────────────────────────────┤
│ 네이버 지도 쿠키 │
│ [NNB=xxx; JSESSIONID=xxx; ...] [수정] │
│ 마지막 수정: 2024-01-15 14:30 │
│ │
│ 인스타그램 쿠키 │
│ [sessionid=xxx; csrftoken=xxx; ...][수정]│
│ 마지막 수정: 2024-01-15 14:30 │
└─────────────────────────────────────────┘
쿠키 획득 방법:
- 브라우저에서 해당 서비스에 로그인
- 개발자 도구 (F12) → Application → Cookies
- 모든 쿠키를
이름=값; 이름=값; ...형식으로 복사 - 관리자 대시보드에서 저장
이미지 소스별 API
# 전체 이미지 조회
GET /api/profile/pension/:id/images
# 소스별 필터링
GET /api/profile/pension/:id/images?source=naver
GET /api/profile/pension/:id/images?source=google
GET /api/profile/pension/:id/images?source=instagram
GET /api/profile/pension/:id/images?source=upload
# 소스별 통계
GET /api/profile/pension/:id/images/stats
# 응답: { total: 50, naver: 20, google: 15, instagram: 10, upload: 5 }
주의사항
- 쿠키 만료: 로그인 세션 쿠키는 일정 기간 후 만료됩니다. 크롤링 실패 시 쿠키를 다시 설정하세요.
- 인스타그램 제한: 인스타그램은 비로그인 상태에서 접근이 제한됩니다. 반드시 쿠키를 설정하세요.
- API 호출 제한: 과도한 크롤링은 차단될 수 있습니다. 적절한 간격을 두고 사용하세요.
B9. 시스템 모니터링
시스템 상태 확인
관리자 대시보드 → 시스템 메뉴에서 확인:
| 항목 | 설명 |
|---|---|
| 서버 상태 | Node.js 프로세스 상태 |
| 데이터베이스 | SQLite 연결 상태 |
| 메모리 사용량 | 현재 메모리 사용률 |
| 디스크 사용량 | 스토리지 사용률 |
| 외부 서비스 | Gemini, Suno, YouTube API 상태 |
로그 확인
# PM2 로그 확인
pm2 logs castad-server
# 실시간 로그 모니터링
pm2 monit
# 로그 파일 직접 확인
tail -f ~/.pm2/logs/castad-server-out.log
tail -f ~/.pm2/logs/castad-server-error.log
프로세스 모니터링
# PM2 상태 확인
pm2 status
# 상세 정보
pm2 show castad-server
# 재시작
pm2 restart castad-server
# 중지
pm2 stop castad-server
B10. 백업 및 복구
데이터베이스 백업
# SQLite 데이터베이스 백업
cp server/database.sqlite backups/database_$(date +%Y%m%d).sqlite
# 자동 백업 (cron 설정)
# 매일 새벽 3시 백업
0 3 * * * cp /path/to/server/database.sqlite /path/to/backups/db_$(date +\%Y\%m\%d).sqlite
미디어 파일 백업
# 영상 파일 백업
tar -czf backups/downloads_$(date +%Y%m%d).tar.gz server/downloads/
# 에셋 파일 백업
tar -czf backups/assets_$(date +%Y%m%d).tar.gz server/assets/
전체 백업
#!/bin/bash
# backup.sh
BACKUP_DIR="/path/to/backups"
DATE=$(date +%Y%m%d_%H%M%S)
# 데이터베이스
cp server/database.sqlite $BACKUP_DIR/db_$DATE.sqlite
# 미디어 파일
tar -czf $BACKUP_DIR/media_$DATE.tar.gz server/downloads/ server/assets/
# 설정 파일 (환경 변수 제외)
cp .env.example $BACKUP_DIR/env_example_$DATE
# 7일 이상 된 백업 삭제
find $BACKUP_DIR -type f -mtime +7 -delete
echo "Backup completed: $DATE"
복구
# 데이터베이스 복구
cp backups/database_YYYYMMDD.sqlite server/database.sqlite
# 미디어 파일 복구
tar -xzf backups/downloads_YYYYMMDD.tar.gz -C server/
# 서버 재시작
pm2 restart castad-server
B11. 트러블슈팅
자주 발생하는 오류
1. Puppeteer 실행 오류
Error: Failed to launch the browser process
해결 방법:
# Chrome/Chromium 의존성 설치 (Ubuntu)
sudo apt install -y ca-certificates fonts-liberation libasound2 libatk-bridge2.0-0 \
libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 \
libgbm1 libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 \
libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \
libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 \
libxss1 libxtst6 lsb-release wget xdg-utils
2. SQLite 잠금 오류
SQLITE_BUSY: database is locked
해결 방법:
# WAL 모드 활성화 (server/db.js에 추가)
db.run("PRAGMA journal_mode=WAL;");
# 또는 서버 재시작
pm2 restart castad-server
3. YouTube API 할당량 초과
Error: quotaExceeded
해결 방법:
- 일일 할당량: 10,000 units
- 업로드 1건 = 1,600 units (하루 최대 6건)
- Google Cloud Console에서 할당량 증가 요청
4. 메모리 부족
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
해결 방법:
# Node.js 메모리 한도 증가
export NODE_OPTIONS="--max-old-space-size=4096"
# PM2 설정
pm2 start index.js --node-args="--max-old-space-size=4096"
5. FFmpeg 오류
Error: ffmpeg exited with code 1
해결 방법:
# FFmpeg 버전 확인
ffmpeg -version
# 재설치
sudo apt install --reinstall ffmpeg
# 코덱 확인
ffmpeg -codecs | grep libx264
로그 분석
# 오류만 필터링
grep -i "error" ~/.pm2/logs/castad-server-error.log | tail -50
# 특정 날짜 로그
grep "2024-12-06" ~/.pm2/logs/castad-server-out.log
# 실시간 오류 모니터링
tail -f ~/.pm2/logs/castad-server-error.log
Part C. 사용자 매뉴얼 (User Manual)
이 섹션은 CastAD Pro를 사용하여 마케팅 영상을 제작하는 펜션 사업자/일반 사용자를 위한 가이드입니다.
C1. 시작하기
CastAD란?
CastAD는 AI가 자동으로 펜션 홍보 영상을 만들어주는 서비스입니다.
✅ 펜션 사진만 올리면 AI가 광고 문구, 음악, 영상을 만들어줍니다 ✅ 만든 영상을 버튼 하나로 YouTube에 올릴 수 있습니다 ✅ 외국어 자막도 자동 생성됩니다 (영어, 일본어, 중국어 등)
필요한 것
- 인터넷 연결된 컴퓨터 또는 태블릿
- 웹 브라우저 (Chrome 권장)
- 펜션 사진 (권장: 5~15장)
간단 사용법
1. 회원가입 → 로그인
2. 펜션 정보 등록
3. 사진 올리기
4. "영상 생성" 클릭
5. 잠시 기다리기 (약 2~3분)
6. 완성된 영상 다운로드 또는 YouTube 업로드
C2. 회원가입 및 로그인
이메일로 회원가입하기
- CastAD 홈페이지 접속
- 우측 상단 "회원가입" 클릭
- 정보 입력:
- 아이디: 영문/숫자 조합 (예: mypension123)
- 이메일: 실제 사용하는 이메일 (인증 필요)
- 비밀번호: 8자 이상, 영문+숫자+특수문자
- 이름: 본인 이름
- 연락처: 휴대폰 번호
- "가입하기" 버튼 클릭
- 입력한 이메일로 인증 메일 확인
- 메일의 "이메일 인증하기" 버튼 클릭
- 인증 완료! 이제 로그인 가능
소셜 계정으로 회원가입하기
더 간편하게 가입할 수 있습니다:
- 로그인 페이지에서 "Google로 계속하기" 또는 "Naver로 계속하기" 클릭
- 해당 계정으로 로그인
- 권한 동의
- 자동으로 회원가입 및 로그인 완료!
로그인하기
- 홈페이지에서 "로그인" 클릭
- 아이디와 비밀번호 입력
- "로그인" 버튼 클릭
비밀번호를 잊었어요
- 로그인 페이지에서 "비밀번호 찾기" 클릭
- 가입할 때 사용한 이메일 입력
- "비밀번호 재설정 링크 보내기" 클릭
- 이메일 확인 후 링크 클릭
- 새 비밀번호 설정
C3. 펜션 등록하기
왜 펜션을 등록해야 하나요?
펜션 정보를 미리 등록해두면:
- 영상 생성할 때마다 정보를 다시 입력할 필요 없음
- AI가 펜션 특성에 맞는 광고 문구를 더 잘 만듦
- 여러 개의 펜션을 한 계정으로 관리 가능
펜션 등록 방법
방법 1: 직접 입력
-
로그인 후 왼쪽 메뉴에서 "펜션 관리" 클릭
-
"새 펜션 추가" 버튼 클릭
-
펜션 정보 입력:
항목 설명 예시 펜션 이름 한글 이름 하늘빛 풀빌라 영문 이름 영어 이름 Hanulbit Pool Villa 지역 소재 지역 가평 주소 전체 주소 경기도 가평군 청평면... 펜션 유형 해당되는 것 모두 선택 풀빌라, 커플 펜션 주요 시설 보유 시설 선택 수영장, BBQ, 스파 예약 링크 예약 페이지 URL https://... 소개글 펜션 설명 청평호가 보이는... -
"저장" 버튼 클릭
방법 2: URL로 자동 입력 (v3.6.0 확장)
네이버 지도, 구글 지도, 또는 인스타그램 URL을 입력하면 정보가 자동으로 채워집니다!
지원하는 URL 형식:
| 소스 | URL 예시 |
|---|---|
| 네이버 지도 | https://naver.me/... 또는 https://map.naver.com/... |
| 구글 지도 | https://maps.google.com/... 또는 https://goo.gl/maps/... |
| 인스타그램 | https://instagram.com/username 또는 https://www.instagram.com/username |
사용 방법:
- "새 펜션 추가" 클릭
- "URL로 가져오기" 탭 선택
- 원하는 URL 붙여넣기
- "정보 가져오기" 클릭 (URL이 자동으로 인식됩니다)
- 자동으로 채워진 정보 확인 및 수정
- "저장" 클릭
인스타그램 크롤링 참고: 인스타그램에서 사진을 가져오려면 관리자가 인스타그램 쿠키를 설정해야 합니다. 관리자에게 문의하세요.
펜션 수정 및 삭제
- 수정: 펜션 목록에서 해당 펜션의 "수정" 버튼 클릭
- 삭제: 펜션 목록에서 해당 펜션의 "삭제" 버튼 클릭
⚠️ 펜션을 삭제하면 해당 펜션으로 만든 영상 기록도 삭제될 수 있습니다.
C4. 영상 만들기
영상 생성 단계
1단계: 펜션 선택 → 2단계: 옵션 설정 → 3단계: 생성 → 4단계: 결과 확인
1단계: 펜션 선택
- 왼쪽 메뉴에서 "새 프로젝트" 클릭
- 등록된 펜션 목록에서 영상을 만들 펜션 선택
- 펜션이 없으면 "새 펜션 등록" 클릭
2단계: 옵션 설정
기본 옵션
| 옵션 | 설명 | 권장 |
|---|---|---|
| 화면 비율 | 16:9 (가로) / 9:16 (세로) | YouTube: 16:9, Shorts: 9:16 |
| 오디오 모드 | 음악 / 내레이션 / 인스트루멘탈 | 음악 권장 |
| 음악 장르 | K-Pop, 발라드, EDM 등 | 펜션 분위기에 맞게 |
| 텍스트 효과 | 글자 표시 스타일 | Cinematic 권장 |
사진 업로드
- 권장 장수: 5~15장
- 권장 해상도: 1920x1080 이상
- 형식: JPG, PNG, WEBP
- 팁:
- 외관, 객실, 수영장, 주변 풍경 등 다양하게
- 밝고 선명한 사진이 좋음
- 사람이 없는 사진 권장
3단계: 생성 시작
- 모든 옵션 설정 확인
- "영상 생성" 버튼 클릭
- 생성 진행 화면 확인:
- 🔄 정보 분석 중...
- 🎵 음악 생성 중...
- 🎬 영상 렌더링 중...
- ✅ 완료!
💡 소요 시간: 보통 2~3분, 이미지 수에 따라 다를 수 있음
4단계: 결과 확인
- 생성된 영상 미리보기
- 마음에 들면:
- "다운로드": 내 컴퓨터에 저장
- "YouTube 업로드": 바로 유튜브에 올리기
- 마음에 안 들면:
- "다시 생성": 옵션 변경 후 재생성
C5. 영상 옵션 상세
화면 비율
| 비율 | 용도 | 크기 |
|---|---|---|
| 16:9 | 일반 YouTube 영상 | 1920x1080 |
| 9:16 | YouTube Shorts, 인스타 릴스, 틱톡 | 1080x1920 |
오디오 모드
| 모드 | 설명 | 용도 |
|---|---|---|
| 음악 | AI가 만든 로고송 | 브랜드 홍보 영상 |
| 내레이션 | AI 성우가 읽어주는 광고 | 정보 전달 위주 |
| 인스트루멘탈 | 가사 없는 배경음악 | 자막 집중형 영상 |
음악 장르
한국어 콘텐츠:
- K-Pop: 신나는 분위기
- 발라드: 감성적인 분위기
- Hip-Hop: 트렌디한 분위기
- EDM: 역동적인 분위기
- 트로트: 친근한 분위기
- 재즈: 고급스러운 분위기
외국어 콘텐츠:
- J-Pop: 일본 대상
- C-Pop: 중국 대상
- Pop: 영미권 대상
텍스트 효과
| 효과 | 설명 | 분위기 |
|---|---|---|
| Neon | 네온사인 효과 | 화려함 |
| Cinematic | 영화 자막 스타일 | 고급스러움 |
| Typewriter | 타자기 효과 | 감성적 |
| Bold | 크게 팝업 | 임팩트 |
| Elegant | 우아한 등장 | 세련됨 |
| Glitch | 글리치 효과 | 트렌디 |
전환 효과
| 효과 | 설명 |
|---|---|
| Mix | 부드러운 디졸브 |
| Zoom | 확대/축소 전환 |
| Slide | 슬라이드 전환 |
| Wipe | 화면 닦아내기 |
C6. YouTube 연동
YouTube 계정 연결하기
- 왼쪽 메뉴에서 "설정" 클릭
- "YouTube 연동" 탭 선택
- "YouTube 계정 연결하기" 버튼 클릭
- Google 로그인 화면에서 YouTube 채널 계정으로 로그인
- 권한 요청 화면에서 "허용" 클릭
- 연결 완료! 채널 이름이 표시됩니다
YouTube에 영상 올리기
-
영상 생성 완료 후 "YouTube 업로드" 클릭
-
업로드 정보 입력:
항목 설명 자동 생성 제목 영상 제목 ✅ AI 생성 설명 영상 설명란 ✅ AI 생성 태그 검색용 키워드 ✅ AI 생성 공개 설정 공개/비공개/미등록 수동 선택 플레이리스트 추가할 재생목록 수동 선택 -
내용 확인 후 "업로드" 클릭
-
업로드 완료 후 "YouTube에서 보기" 클릭
업로드 기본 설정
매번 같은 설정을 하지 않도록 기본값을 저장할 수 있습니다:
- "설정" → "YouTube 연동"
- 기본 설정 변경:
- 기본 공개 설정
- 기본 카테고리
- 기본 태그
- 기본 플레이리스트
- "설정 저장" 클릭
연결 해제
- "설정" → "YouTube 연동"
- "연결 해제" 버튼 클릭
- 확인 대화상자에서 "확인"
C7. TikTok 연동
TikTok 계정 연결하기
- 왼쪽 메뉴에서 "설정" 클릭
- "TikTok 연동" 탭 선택
- "TikTok 계정 연결하기" 버튼 클릭
- TikTok 로그인 화면에서 계정으로 로그인
- 권한 요청 화면에서 "승인" 클릭
- 연결 완료! 프로필 정보가 표시됩니다
TikTok에 영상 올리기
-
영상 생성 완료 후 "TikTok 업로드" 클릭
-
업로드 방식 선택:
방식 설명 권장 Direct Post 즉시 TikTok에 게시 빠른 업로드 Inbox (초안) TikTok 앱에서 편집 후 게시 추가 편집 필요시 -
업로드 정보 입력:
항목 설명 제목 영상 캡션 (150자 제한) 공개 설정 나만 보기/팔로워만/전체 공개 듀엣 허용 다른 사람이 듀엣 가능 여부 댓글 허용 댓글 작성 허용 여부 스티치 허용 스티치 기능 허용 여부 -
"업로드" 클릭
TikTok 업로드 기본 설정
- "설정" → "TikTok 연동"
- 기본 설정 변경:
- 기본 공개 설정
- 듀엣/댓글/스티치 허용 여부
- 기본 해시태그
- 업로드 방식 (Direct/Inbox)
- "설정 저장" 클릭
TikTok 영상 주의사항
💡 팁: TikTok은 세로 영상(9:16)에 최적화되어 있습니다.
- 영상 길이: 3초 ~ 10분
- 파일 크기: 최대 4GB
- 권장 해상도: 1080x1920 (Full HD 세로)
C8. Instagram 연동
Instagram 계정 연결하기
⚠️ 참고: Instagram은 보안상의 이유로 ID/비밀번호로 연결합니다.
- 왼쪽 메뉴에서 "설정" 클릭
- "Instagram 연동" 탭 선택
- "Instagram 계정 연결하기" 버튼 클릭
- Instagram 로그인 정보 입력:
- 사용자 이름 (또는 이메일)
- 비밀번호
- 2단계 인증 활성화된 경우:
- 인증 코드 입력 (SMS 또는 앱)
- 연결 완료! 프로필 정보가 표시됩니다
Instagram에 릴스 올리기
-
영상 생성 완료 후 "Instagram 업로드" 클릭
-
업로드 정보 입력:
항목 설명 캡션 게시물 설명 해시태그 검색용 해시태그 (기본 제공) -
"업로드" 클릭
-
업로드 완료 후 Instagram에서 확인
Instagram 업로드 제한
Instagram 계정 보호를 위해 다음 제한이 적용됩니다:
| 항목 | 제한 |
|---|---|
| 주간 업로드 | 기본 1회 (설정 변경 가능) |
| 영상 길이 | 최대 90초 |
| 비율 | 9:16 (세로) 권장 |
Instagram 기본 설정
- "설정" → "Instagram 연동"
- 기본 설정 변경:
- 기본 캡션 템플릿
- 기본 해시태그
- 주간 업로드 제한
- 업로드 알림
- "설정 저장" 클릭
Instagram 연결 해제
- "설정" → "Instagram 연동"
- "연결 해제" 버튼 클릭
- 확인 대화상자에서 "확인"
Instagram 주의사항
⚠️ 중요: Instagram 사용 시 주의하세요!
- 과도한 업로드 금지: 하루에 여러 번 업로드하면 계정이 제한될 수 있습니다
- 비즈니스 계정 권장: 일반 계정보다 제한이 적습니다
- 2FA 활성화 권장: 계정 보안을 위해 2단계 인증을 켜세요
- 업로드 간격 유지: 최소 24시간 간격 권장
C9. 영상 관리
라이브러리 확인
왼쪽 메뉴의 **"라이브러리"**에서 생성한 모든 영상을 볼 수 있습니다.
영상 목록 정보
| 항목 | 설명 |
|---|---|
| 썸네일 | 영상 미리보기 이미지 |
| 제목 | 펜션 이름 + 생성 날짜 |
| 생성일 | 영상을 만든 날짜 |
| 상태 | 업로드됨/미업로드 |
| 펜션 | 연결된 펜션 |
영상 필터링
- 펜션별: 특정 펜션의 영상만 보기
- 상태별: 업로드됨/미업로드 필터
- 날짜순: 최신순/오래된순 정렬
영상 관리 기능
| 기능 | 설명 |
|---|---|
| 다운로드 | MP4 파일로 저장 |
| 미리보기 | 영상 재생 |
| YouTube 업로드 | 아직 안 올린 영상 업로드 |
| 삭제 | 영상 삭제 (복구 불가) |
C10. 에셋 관리
에셋이란?
에셋은 영상 제작에 사용된 모든 파일입니다:
- 이미지: 업로드한 사진, 크롤링한 사진, AI 생성 이미지
- 오디오: AI가 만든 음악
- 비디오: 완성된 영상 파일
에셋 확인하기
- 왼쪽 메뉴에서 "에셋" 클릭
- 스토리지 사용량 확인
- 에셋 목록 확인
스토리지 관리
| 플랜 | 스토리지 한도 |
|---|---|
| Free | 500MB |
| Basic | 2GB |
| Pro | 10GB |
| Business | 50GB |
스토리지가 부족하면:
- 불필요한 에셋 삭제
- 플랜 업그레이드
에셋 삭제
- 에셋 목록에서 삭제할 항목 선택
- "삭제" 버튼 클릭
- 확인 후 삭제 완료
⚠️ 삭제된 에셋은 복구할 수 없습니다.
C11. 계정 설정
프로필 수정
- 왼쪽 메뉴에서 "계정" 클릭
- 수정할 정보 변경:
- 이름
- 연락처
- 이메일
- "저장" 클릭
비밀번호 변경
- "계정" → "비밀번호 변경"
- 현재 비밀번호 입력
- 새 비밀번호 입력 (8자 이상)
- 새 비밀번호 확인
- "변경" 클릭
언어 설정
CastAD는 6개 언어를 지원합니다:
| 언어 | 설정 |
|---|---|
| 한국어 | 기본값 |
| English | 영어 |
| 日本語 | 일본어 |
| 中文 | 중국어 |
| ไทย | 태국어 |
| Tiếng Việt | 베트남어 |
변경 방법:
- 상단 헤더의 언어 버튼 클릭
- 원하는 언어 선택
- 즉시 적용
테마 설정
- 라이트 모드: 밝은 화면
- 다크 모드: 어두운 화면
- 시스템: 기기 설정 따름
변경 방법:
- 상단 헤더의 테마 버튼 클릭
- 원하는 테마 선택
C12. 구독 및 요금제
요금제 안내
| 플랜 | 가격 | 월간 영상 | 펜션 수 | 스토리지 |
|---|---|---|---|---|
| Free | 무료 | 10개 | 1개 | 500MB |
| Basic | ₩29,000/월 | 15개 | 1개 | 2GB |
| Pro | ₩89,000/월 | 75개 | 5개 | 10GB |
| Business | ₩249,000/월 | 무제한 | 무제한 | 50GB |
크레딧이란?
- 영상 1개 생성 = 크레딧 1개 소모
- 매월 플랜에 따라 크레딧 자동 충전
- 미사용 크레딧은 이월되지 않음
남은 크레딧 확인
- 상단 헤더에 현재 크레딧 표시
- "계정" 페이지에서 상세 확인
크레딧 충전 요청
무료 플랜에서 추가 크레딧이 필요하면:
- "계정" → "크레딧 충전 요청"
- 요청 사유 입력
- "요청하기" 클릭
- 관리자 승인 후 크레딧 지급
플랜 업그레이드
더 많은 기능이 필요하면:
- "계정" → "구독 관리"
- 원하는 플랜 선택
- 결제 진행
- 즉시 적용
C13. 자주 묻는 질문 (FAQ)
가입/로그인 관련
Q: 회원가입 인증 메일이 안 와요.
A: 스팸 메일함을 확인해주세요. 그래도 없으면 **"인증 메일 재발송"**을 클릭하세요.
Q: 비밀번호를 잊었어요.
A: 로그인 페이지에서 **"비밀번호 찾기"**를 클릭하고 이메일을 입력하세요.
Q: 소셜 로그인을 다른 계정으로 바꾸고 싶어요.
A: 계정 설정에서 현재 소셜 연결을 해제한 후 다시 연결하세요.
영상 생성 관련
Q: 영상 생성이 오래 걸려요.
A: 보통 2~3분 소요됩니다. 이미지가 많거나 고화질이면 더 오래 걸릴 수 있습니다.
Q: 영상 생성 중 오류가 발생했어요.
A: 새로고침 후 다시 시도해주세요. 계속 오류가 나면 이미지 파일을 확인하거나 다른 이미지로 시도해보세요.
Q: 음악이 마음에 안 들어요.
A: 다른 장르를 선택하거나 **"다시 생성"**을 눌러 새로운 음악을 받아보세요.
Q: 영상에 내 로고를 넣을 수 있나요?
A: 현재 버전에서는 지원하지 않습니다. 향후 업데이트 예정입니다.
YouTube 관련
Q: YouTube 연결이 안 돼요.
A: 팝업 차단을 해제하고, YouTube 채널이 있는 Google 계정으로 로그인했는지 확인하세요.
Q: 업로드한 영상이 YouTube에서 안 보여요.
A: 공개 설정이 **"비공개"**나 **"미등록"**이면 일반 검색에서 안 보입니다. YouTube Studio에서 확인하세요.
Q: YouTube 연결을 해제하면 업로드한 영상은 어떻게 되나요?
A: 이미 업로드된 영상은 그대로 YouTube에 남아있습니다.
결제/플랜 관련
Q: 무료 크레딧을 다 썼어요.
A: 다음 달까지 기다리거나, 플랜을 업그레이드하거나, 크레딧 충전을 요청하세요.
Q: 플랜 업그레이드하면 즉시 적용되나요?
A: 네, 결제 완료 즉시 적용됩니다.
Q: 환불 가능한가요?
A: 결제 후 7일 이내 미사용 시 환불 가능합니다. 고객센터로 문의하세요.
기타
Q: 모바일에서도 사용 가능한가요?
A: 네, 모바일 웹 브라우저에서 사용 가능합니다. 다만 PC에서 사용을 권장합니다.
Q: 영상 저작권은 누구에게 있나요?
A: 생성된 영상의 저작권은 사용자에게 있습니다. 자유롭게 사용하세요.
Q: 고객 지원은 어떻게 받나요?
A: 앱 내 "문의하기" 또는 이메일 support@castad.com으로 연락하세요.
Part D. 마케터 매뉴얼 (Marketer Manual)
이 섹션은 CaStAD의 마케팅을 담당하는 마케터를 위한 가이드입니다.
D1. CaStAD 마케팅 전략
브랜드 포지셔닝
CaStAD = 커스터드(Custard) 🍮
커스터드 디저트처럼 정밀하고, 부드럽고, 달콤한 마케팅 솔루션
| 핵심 가치 | 의미 | 마케팅 메시지 |
|---|---|---|
| 정밀함 (달걀) | 3-6도 온도 관리 | "AI가 정밀하게 분석합니다" |
| 부드러움 (우유) | 크리미한 결과물 | "부드러운 사용자 경험" |
| 달콤함 (설탕) | 만족스러운 성과 | "달콤한 마케팅 성과" |
핵심 USP (Unique Selling Proposition)
1. 1분 만에 전문가급 영상 생성
2. URL 하나로 모든 정보 자동 수집
3. 6개 언어 자동 SEO 최적화
4. YouTube/TikTok 원클릭 업로드
5. 펜션 특화 AI (500+ 학습 데이터)
캠페인 슬로건
| 상황 | 슬로건 |
|---|---|
| 메인 | "펜션 홍보, 1분이면 충분" |
| 시간 절약 | "7일 → 3분, 99% 시간 절약" |
| 비용 절감 | "100만원 → 1만원, 99% 비용 절감" |
| 성과 강조 | "평균 340% 예약 증가" |
| 신뢰 | "500+ 펜션이 선택한 이유" |
D2. 타겟 고객 분석
주요 타겟 페르소나
페르소나 1: 김사장님 (50대 남성)
- 직업: 펜션 단독 운영자
- 고민: SNS 마케팅 방법을 모름
- 니즈: 쉽고 빠르게 홍보하고 싶음
- 결정 요인: 사용 편의성, 가격
- 접점: 네이버 카페, 지역 상공회의소
페르소나 2: 이대표님 (40대 남성)
- 직업: 펜션 프랜차이즈 대표 (5개 운영)
- 고민: 각 펜션별 마케팅 관리 어려움
- 니즈: 통합 관리 + 성과 분석
- 결정 요인: 다중 펜션 관리, 분석 기능
- 접점: LinkedIn, 업계 세미나
페르소나 3: 박실장님 (30대 여성)
- 직업: 숙박업 마케팅 대행사 실장
- 고민: 클라이언트별 영상 제작 시간
- 니즈: 대량 생산 + 고품질 유지
- 결정 요인: API 연동, 화이트라벨
- 접점: 마케팅 커뮤니티, 인스타그램
고객 여정 맵 (Customer Journey)
flowchart LR
A[인지] --> B[관심]
B --> C[고려]
C --> D[구매]
D --> E[충성]
A -- "SNS 광고/검색" --> B
B -- "랜딩페이지 방문" --> C
C -- "무료 체험" --> D
D -- "유료 전환" --> E
채널별 타겟 전략
| 채널 | 타겟 | 메시지 |
|---|---|---|
| 네이버 | 펜션 사장님 | "펜션 홍보 방법" 키워드 공략 |
| 인스타그램 | 젊은 운영자 | 비포/애프터 릴스 콘텐츠 |
| YouTube | 정보 탐색자 | 튜토리얼 + 성공 사례 |
| 카카오톡 | 기존 고객 | 신기능 안내, 리텐션 |
| B2B 대행사 | 화이트라벨/API 제안 |
D3. 콘텐츠 마케팅
콘텐츠 유형별 가이드
1. 블로그/SEO 콘텐츠
타겟 키워드:
- "펜션 홍보 방법"
- "숙박업 마케팅"
- "펜션 영상 제작"
- "인스타 릴스 만들기"
- "숙소 유튜브 마케팅"
콘텐츠 구조:
1. 문제 제기 (펜션 마케팅 어려움)
2. 해결책 제시 (AI 영상 생성)
3. 사용법 안내 (단계별 가이드)
4. 성공 사례 (실제 고객 후기)
5. CTA (무료 체험 유도)
2. 소셜 미디어 콘텐츠
인스타그램 릴스 템플릿
[Hook - 3초]
"펜션 사장님들 영상 편집하느라 밤새세요?"
[Problem - 5초]
"외주 맡기면 100만원, 직접 하면 7일..."
[Solution - 7초]
"AI가 1분 만에 만들어드립니다"
[Demo - 10초]
(실제 영상 생성 화면)
[CTA - 5초]
"프로필 링크에서 무료 체험하세요"
YouTube Shorts 스크립트
[썸네일] "100만원 vs 1만원 영상 비교"
00:00 "왼쪽은 마케팅 대행사, 오른쪽은 AI"
00:05 "어떤 게 더 좋아 보여요?"
00:10 "정답은... 둘 다 AI입니다"
00:15 "CaStAD로 만들었어요"
00:20 "무료로 시작해보세요"
3. 이메일 마케팅
웰컴 시퀀스
Day 1: 가입 감사 + 첫 영상 만들기 가이드
Day 3: 성공 사례 소개 + 팁
Day 5: 미사용 시 리마인더
Day 7: 무료 크레딧 추가 제안
Day 14: 유료 플랜 할인 쿠폰
D4. SNS 마케팅 가이드
플랫폼별 전략
인스타그램
| 항목 | 전략 |
|---|---|
| 콘텐츠 | 릴스 80%, 피드 15%, 스토리 5% |
| 빈도 | 릴스 주 3회, 피드 주 1회 |
| 해시태그 | #펜션마케팅 #숙박업홍보 #AI영상 |
| 최적 시간 | 화/목 저녁 8-10시 |
YouTube
| 항목 | 전략 |
|---|---|
| 콘텐츠 | Shorts 70%, 롱폼 30% |
| Shorts | 사용법, 비포/애프터, 꿀팁 |
| 롱폼 | 상세 튜토리얼, 인터뷰 |
| SEO | 제목에 "펜션 홍보" 키워드 |
TikTok
| 항목 | 전략 |
|---|---|
| 콘텐츠 | 트렌드 활용 + 제품 소개 |
| 톤앤매너 | 캐주얼, 유머 가미 |
| 음악 | 트렌딩 사운드 활용 |
| 챌린지 | #1분영상챌린지 기획 |
인플루언서 협업
| 티어 | 팔로워 | 협업 방식 | 예상 비용 |
|---|---|---|---|
| 마이크로 | 1K-10K | 무료 체험 제공 | 무료~10만원 |
| 미드 | 10K-100K | 유료 리뷰 | 30-100만원 |
| 매크로 | 100K+ | 브랜드 앰버서더 | 협의 |
D5. 성과 측정 및 KPI
핵심 KPI
Acquisition (획득)
| 지표 | 목표 | 측정 방법 |
|---|---|---|
| 웹사이트 방문자 | 월 10,000명 | Google Analytics |
| 회원가입 수 | 월 500명 | 내부 DB |
| 가입 전환율 | 5% | 방문자 대비 가입 |
| CAC | ₩10,000 이하 | 광고비 / 신규 가입 |
Activation (활성화)
| 지표 | 목표 | 측정 방법 |
|---|---|---|
| 첫 영상 생성률 | 70% | 가입 후 7일 내 |
| 활성 사용자(DAU) | 200명 | 일일 접속자 |
| 평균 세션 시간 | 5분+ | Analytics |
Revenue (수익)
| 지표 | 목표 | 측정 방법 |
|---|---|---|
| 유료 전환율 | 10% | 무료→유료 전환 |
| ARPU | ₩50,000 | 총 매출/활성 사용자 |
| MRR | ₩50,000,000 | 월 반복 매출 |
| LTV | ₩500,000 | 고객 생애 가치 |
Retention (유지)
| 지표 | 목표 | 측정 방법 |
|---|---|---|
| 월간 재방문율 | 60% | 30일 리텐션 |
| Churn Rate | 5% 이하 | 월간 이탈률 |
| NPS | 50+ | 분기별 설문 |
D6. 캠페인 사례
성공 캠페인 예시
캠페인: "7일 → 3분" 챌린지
목표: 신규 가입 500명
기간: 2주
채널: 인스타그램 릴스
예산: 200만원
결과:
- 노출: 150만 회
- 가입: 623명 (+24.6%)
- CPA: 3,200원
- ROAS: 420%
캠페인: 펜션 사장님 인터뷰
목표: 신뢰도 향상
형식: YouTube 롱폼 (5분)
내용: 실제 사용자 성공 스토리
결과:
- 조회수: 8.2만
- 평균 시청 시간: 3분 42초
- 유입 가입: 312명
Part E. 영업사원 매뉴얼 (Sales Manual)
이 섹션은 CaStAD를 판매하는 영업사원을 위한 가이드입니다.
E1. 제품 이해하기
한 문장 정의
CaStAD는 펜션/숙박업소를 위한 AI 마케팅 영상 자동 생성 및 멀티 플랫폼 관리 SaaS입니다.
엘리베이터 피치 (30초)
"펜션 사장님, 영상 마케팅 하려면 보통 100만원에 일주일 걸리잖아요?
CaStAD는 AI가 1분 만에 전문가급 홍보 영상을 만들어주고,
버튼 하나로 YouTube, TikTok에 자동 업로드까지 해줍니다.
월 2만9천원으로 시작할 수 있고, 지금 무료 체험도 가능합니다."
핵심 기능 요약
| 기능 | 고객 가치 | 경쟁 우위 |
|---|---|---|
| AI 영상 생성 | 시간 99% 절약 | 펜션 특화 학습 |
| URL 자동 크롤링 | 입력 작업 불필요 | 네이버/구글 지도 지원 |
| AI 음악/로고송 | 저작권 걱정 없음 | Suno AI 연동 |
| 6개 언어 SEO | 해외 고객 유치 | 한/영/일/중/태/베 |
| 다중 펜션 관리 | 효율적 운영 | 1계정 N펜션 |
| YouTube/TikTok 연동 | 원클릭 업로드 | OAuth 자동화 |
E2. 타겟 시장 및 고객
시장 규모
한국 펜션 시장:
- 전국 펜션 수: 약 20,000개
- 연간 성장률: 5%
- 마케팅 예산: 평균 월 50만원
TAM (전체 시장): 20,000 × 50만원 × 12개월 = 1,200억원/년
SAM (접근 가능): 5,000개 × 10만원 × 12개월 = 60억원/년
SOM (초기 목표): 500개 × 5만원 × 12개월 = 3억원/년
이상적인 고객 프로필 (ICP)
| 특성 | 이상적 고객 |
|---|---|
| 업종 | 펜션, 풀빌라, 글램핑, 리조트 |
| 규모 | 객실 5-30개 |
| 위치 | 관광지 (가평, 제주, 강원, 부산) |
| 운영 형태 | 직접 운영 or 소규모 법인 |
| 마케팅 현황 | SNS 하고 싶지만 방법 모름 |
| 예산 | 월 10-30만원 마케팅 예산 |
고객 발굴 채널
| 채널 | 방법 | 예상 전환율 |
|---|---|---|
| 인바운드 리드 | 웹사이트 문의 | 20-30% |
| 네이버 카페 | 펜션 운영자 커뮤니티 | 5-10% |
| 직접 연락 | 네이버 플레이스 검색 | 3-5% |
| 제휴 | 숙박 플랫폼, 상공회의소 | 15-20% |
| 추천 | 기존 고객 소개 | 30-40% |
E3. 세일즈 피치
상황별 오프닝
콜드콜 오프닝
"안녕하세요, 사장님. 저는 CaStAD의 OOO입니다.
혹시 펜션 홍보 영상 만드시는 데 어려움 없으셨어요?
저희가 AI로 1분 만에 영상 만들어드리는 서비스를 하고 있는데,
잠깐 2분만 설명드려도 될까요?"
인바운드 리드 오프닝
"안녕하세요, 사장님. CaStAD 문의 주셔서 감사합니다.
어떤 점이 궁금하셔서 문의 주셨나요?
(고객 니즈 파악 후) 아, 그 부분이라면 저희 서비스가 딱 맞을 것 같아요.
제가 화면 공유로 직접 보여드릴까요?"
니즈 파악 질문 (SPIN)
| 유형 | 질문 예시 |
|---|---|
| Situation | "지금 펜션 홍보는 어떻게 하고 계세요?" |
| Problem | "영상 만드실 때 가장 어려운 점이 뭐예요?" |
| Implication | "그러면 예약이 줄어들거나 하진 않으셨어요?" |
| Need-payoff | "만약 영상을 1분 만에 만들 수 있다면 어떠실 것 같아요?" |
데모 스크립트 (5분)
[1분] 소개
"지금부터 실제로 영상 만드는 걸 보여드릴게요."
[2분] URL 입력 → 자동 정보 수집
"이렇게 네이버 지도 URL만 붙여넣으면..."
"보세요, 펜션 이름, 사진, 위치가 자동으로 들어왔죠?"
[1분] 옵션 설정 → 생성
"음악 스타일 선택하시고... 생성 버튼 클릭!"
"AI가 지금 영상을 만들고 있어요."
[1분] 결과 + CTA
"짠! 2분 만에 완성됐습니다. 어떠세요?"
"오늘 가입하시면 무료로 3개 영상 만들어보실 수 있어요."
E4. 가격 정책 및 협상
공식 가격표
| 플랜 | 월 가격 | 영상/월 | 펜션 수 | 타겟 |
|---|---|---|---|---|
| Free | 무료 | 10회 | 1개 | 체험 |
| Basic | ₩29,000 | 15회 | 1개 | 소규모 |
| Pro | ₩89,000 | 75회 | 5개 | 다중 운영 |
| Business | ₩249,000 | 무제한 | 무제한 | 대행사 |
할인 정책
| 조건 | 할인 | 승인 |
|---|---|---|
| 연간 결제 | 20% | 자동 |
| 3개월 선결제 | 10% | 자동 |
| 단체 (5+) | 15% | 팀장 승인 |
| 대행사 파트너 | 별도 협의 | 임원 승인 |
가격 이의 대응
"너무 비싸요"
"이해합니다. 그런데 사장님, 혹시 외주 맡기면 영상 하나에 얼마 하는지 아세요?
보통 50-100만원이에요. 저희는 월 2만9천원으로 15개 만드실 수 있어요.
영상당 2천원도 안 되는 거죠."
"무료로 써볼게요"
"네, 물론이죠! 무료로 3개 먼저 만들어보시고,
마음에 드시면 그때 결정하세요.
다만 지금 가입하시면 첫 달 50% 할인 쿠폰 드려요."
E5. 경쟁사 비교
직접 경쟁사
| 항목 | CaStAD | 경쟁사 A | 경쟁사 B |
|---|---|---|---|
| 영상 생성 시간 | 2분 | 10분+ | 30분+ |
| 펜션 특화 | ✅ | ❌ | ❌ |
| 다국어 SEO | 6개 언어 | 영어만 | ❌ |
| AI 음악 | ✅ | ❌ | 유료 |
| YouTube 연동 | OAuth | 수동 | 수동 |
| TikTok 연동 | ✅ | ❌ | ❌ |
| 가격 | ₩29,000~ | ₩50,000~ | ₩100,000~ |
간접 경쟁사 대응
"그냥 직접 만들면 되잖아요"
"맞아요, 직접 만들 수도 있죠. 그런데 사장님 시간당 가치가 얼마예요?
영상 편집 배우고 만드는 데 10시간 쓰시면, 그 시간에 예약 10건 받으실 수 있잖아요.
저희한테 맡기시면 10분이면 끝나요."
"마케팅 대행사 쓰면 되죠"
"대행사도 좋죠. 그런데 월 100만원 이상 들고, 수정하려면 또 기다려야 해요.
저희는 월 3만원에 직접 바로바로 수정할 수 있어요.
일단 무료로 비교해보시는 건 어떠세요?"
E6. 이의 처리
자주 나오는 이의
"나중에 다시 연락주세요"
반박: "네, 언제쯤 연락드릴까요? 혹시 다음 주 화요일 오후 2시 괜찮으세요?"
핵심: 구체적 일정 잡기
"생각해볼게요"
반박: "물론이죠. 혹시 어떤 부분이 고민되시는지 여쭤봐도 될까요?
제가 추가로 설명드릴 수 있으면 드리고 싶어서요."
핵심: 진짜 고민 포인트 파악
"우리 펜션에는 안 맞을 것 같아요"
반박: "어떤 점이 안 맞으실 것 같으세요?
저희가 이미 [비슷한 펜션 유형] 500개 이상 사용 중인데,
혹시 같은 지역 사례 보여드릴까요?"
핵심: 유사 사례로 신뢰 구축
"효과가 있을지 모르겠어요"
반박: "당연히 걱정되시죠. 저희 고객사 평균 예약 증가율이 340%예요.
무료로 먼저 테스트해보시고, 효과 없으면 안 쓰시면 되잖아요.
리스크가 없는 거죠."
핵심: 데이터 + 무료 체험으로 리스크 제거
E7. 클로징 전략
클로징 타이밍 신호
| 신호 | 대응 |
|---|---|
| "가격이 어떻게 되죠?" | 바로 결제 유도 |
| "다른 펜션도 쓰나요?" | 사례 → 클로징 |
| "기능이 더 있어요?" | 기능 설명 → 클로징 |
| "언제부터 쓸 수 있어요?" | 즉시 시작 가능 강조 |
클로징 기법
대안 제시 클로징
"사장님, Basic이랑 Pro 중에 어떤 게 더 맞으실 것 같으세요?
펜션 1개만 하시면 Basic, 나중에 확장 생각하시면 Pro 추천드려요."
희소성 클로징
"지금 가입하시면 이번 달까지만 첫 달 50% 할인 적용해드려요.
내일부터는 정상가예요."
시험 사용 클로징
"일단 무료로 3개 만들어보세요. 마음에 안 드시면 안 쓰시면 되고요.
지금 가입하시면 5분 뒤에 첫 영상 보실 수 있어요."
계약 후 체크리스트
✅ 결제 완료 확인
✅ 웰컴 이메일 발송 확인
✅ 첫 영상 생성 가이드 안내
✅ 3일 후 팔로업 전화 일정 등록
✅ 1주일 후 만족도 체크 일정 등록
✅ 고객 성공 팀에 핸드오프
🏗️ 시스템 아키텍처
현재 아키텍처 (Single Server)
구성 요소:
- Frontend: React 19 + Vite (Port 5173)
- Backend: Express.js (Port 3001) - Auth, Render, API Proxy Services
- Database: SQLite (File-based)
- Storage: Local Filesystem (downloads/, temp/, uploads/)
- External APIs: Gemini (AI), Suno (Music), YouTube (Upload)
대규모 분산 아키텍처 (Scale-Out)
핵심 구성 요소:
- Load Balancer: nginx / AWS ALB - 트래픽 분산
- API Servers: 다중 Express.js 인스턴스 (수평 확장)
- Redis: 세션, 캐시, 작업 큐 (Bull Queue)
- PostgreSQL: Primary + Read Replica 구성
- S3/MinIO: 영상, 이미지, 에셋 저장소
- Render Workers: Puppeteer + FFmpeg (GPU 노드 권장)
- Upload Workers: YouTube, Instagram, TikTok 병렬 업로드
Docker Compose 구성 (개발/소규모)
# docker-compose.yml
version: '3.8'
services:
# Nginx Load Balancer
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- api1
- api2
# API Servers
api1:
build: .
environment:
- NODE_ENV=production
- REDIS_URL=redis://redis:6379
- DATABASE_URL=postgresql://user:pass@postgres:5432/castad
- S3_ENDPOINT=http://minio:9000
depends_on:
- redis
- postgres
api2:
build: .
environment:
- NODE_ENV=production
- REDIS_URL=redis://redis:6379
- DATABASE_URL=postgresql://user:pass@postgres:5432/castad
- S3_ENDPOINT=http://minio:9000
depends_on:
- redis
- postgres
# Render Workers
render-worker:
build:
context: .
dockerfile: Dockerfile.render
deploy:
replicas: 3
environment:
- REDIS_URL=redis://redis:6379
- S3_ENDPOINT=http://minio:9000
# Upload Workers
upload-worker:
build:
context: .
dockerfile: Dockerfile.upload
deploy:
replicas: 2
environment:
- REDIS_URL=redis://redis:6379
# Redis
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
command: redis-server --appendonly yes
# PostgreSQL
postgres:
image: postgres:15-alpine
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=castad
volumes:
- postgres_data:/var/lib/postgresql/data
# MinIO (S3-compatible)
minio:
image: minio/minio
ports:
- "9000:9000"
- "9001:9001"
volumes:
- minio_data:/data
command: server /data --console-address ":9001"
volumes:
redis_data:
postgres_data:
minio_data:
Kubernetes 구조 (대규모)
Kubernetes 리소스:
- Ingress Controller: nginx-ingress / Traefik (TLS 종료)
- Deployments with HPA:
- API Server: 2-10 pods (CPU 기반 auto-scaling)
- Render Worker: 3-20 pods (GPU 노드, 큐 길이 기반)
- Upload Worker: 2-5 pods
- StatefulSets: PostgreSQL (Primary + Replicas), Redis Cluster (3-node)
- External Services: AWS S3, Gemini API, Suno API, YouTube/Instagram/TikTok APIs
마이그레이션 로드맵
| 단계 | 규모 | 주요 변경 | 예상 동시 사용자 |
|---|---|---|---|
| 1단계 | 현재 | Single Server + SQLite | ~50명 |
| 2단계 | 소규모 | Docker Compose + PostgreSQL + Redis | ~500명 |
| 3단계 | 중규모 | Kubernetes (3노드) + S3 | ~5,000명 |
| 4단계 | 대규모 | Multi-AZ K8s + Auto Scaling | ~50,000명+ |
각 단계별 주요 작업
2단계 (Docker Compose)
- SQLite → PostgreSQL 마이그레이션
- Redis 도입 (세션, 캐시, 작업 큐)
- Bull Queue로 렌더링 작업 분리
- MinIO로 파일 저장소 분리
- Docker 이미지 빌드 및 compose 구성
3단계 (Kubernetes)
- Helm Chart 작성
- HPA(Horizontal Pod Autoscaler) 설정
- PersistentVolume 구성
- Ingress 설정 (TLS 포함)
- 모니터링 (Prometheus + Grafana)
4단계 (Multi-AZ)
- Multi-AZ PostgreSQL (RDS 또는 Cloud SQL)
- Redis Cluster (ElastiCache 또는 MemoryStore)
- CDN 설정 (CloudFront 또는 Cloud CDN)
- 글로벌 로드밸런싱
📅 버전 히스토리
v3.7.0 - Background Render Queue & Platform Upload (Current)
- 🔄 백그라운드 렌더링 큐 시스템:
- 페이지 이동/로그아웃해도 렌더링 작업 계속 진행
- 작업 시작 시 크레딧 선차감, 실패 시 자동 환불
- 계정당 동시 렌더링 1개 제한 (서버 전체 3개)
- 실시간 진행률 폴링 및 완료 알림
| API | 설명 |
|---|---|
POST /api/render/start |
렌더링 작업 시작, jobId 즉시 반환 |
GET /api/render/status/:jobId |
작업 상태/진행률 조회 |
GET /api/render/jobs |
내 작업 목록 조회 |
-
📱 Instagram 업로드 기능:
- ResultPlayer에 Instagram 업로드 버튼 추가
- LibraryView 드롭다운에 YouTube/Instagram 업로드 옵션
- 계정 미연결 시 새 탭에서 설정 페이지 안내
-
💾 새 DB 테이블:
render_jobsrender_jobs ( id TEXT PRIMARY KEY, -- job_xxx_xxx user_id, pension_id, status TEXT, -- pending|processing|completed|failed progress INTEGER, -- 0-100 input_data TEXT, -- JSON output_path TEXT, credits_charged INTEGER, credits_refunded INTEGER, created_at, started_at, completed_at ) -
🔧 프론트엔드 개선:
- ResultPlayer: 큐 기반 렌더링, 폴링, "페이지를 나가도 렌더링 계속" 메시지
- LibraryView: YouTube/Instagram 업로드 버튼 (DropdownMenu)
v3.6.0 - Instagram Crawling & Photo Management
- 📸 인스타그램 사진 크롤링:
- 인스타그램 프로필 URL 입력 시 자동으로 사진 수집
- 쿠키 기반 인증으로 공개/팔로우 계정 접근
- 캐러셀 이미지 지원 (여러 장 게시물)
- 🔑 관리자 쿠키 관리:
- 관리자 대시보드 > 설정에서 API 쿠키 관리
- 네이버 지도 쿠키 / 인스타그램 쿠키 저장
- DB 저장으로 서버 재시작 후에도 유지
- 🗂️ 사진 소스별 분류:
- 크롤링 시 소스 자동 구분:
naver/google/instagram/upload - 소스별 필터링 API 지원 (
?source=naver) - 소스별 통계 조회 API (
/images/stats)
- 크롤링 시 소스 자동 구분:
- 🔧 네이버 크롤링 안정화:
- 네이버 GraphQL API 변경 대응
- 지원되지 않는 필드 제거 (menuImages, bizImages 등)
images+cpImages만 사용하도록 수정
v3.5.0 - Enhanced Image Upload & Extended Capacity
- 📸 이미지 업로드 안정화:
useRef기반 파일 입력으로 브라우저 호환성 개선- 파일 선택 후 업로드 안 되는 버그 수정
- 호버 효과 추가로 UX 개선
- 🖼️ 이미지 용량 대폭 확대 (15장 → 100장):
- 네이버 플레이스 크롤링: 최대 100장
- 구글 지도 크롤링: 최대 100장
- 수동 업로드: 최대 100장
- ⭐ 업로드 이미지 우선순위:
- 수동 업로드한 이미지가 목록 최상단에 배치
- 업로드된 이미지 자동 선택
- 랜덤 선택 시에도 업로드 이미지 우선 포함
- 🌐 다국어 지원 업데이트:
- 한국어, 영어, 일본어, 중국어, 태국어, 베트남어 번역 업데이트
- "최대 100장" 텍스트 전 언어 반영
- 🔧 Google OAuth 프로덕션 설정:
BACKEND_URL환경변수 추가 필요- 프로덕션 리다이렉션 URI 가이드 문서화
v3.4.0 - Business DNA & Smart Image Management
- 🧬 비즈니스 DNA 분석 시스템: Google Search Grounding + Gemini 2.5 Flash
- 펜션 이름/URL 입력 시 AI가 자동으로 브랜드 DNA 분석
- 톤앤매너 (Tone & Manner): 브랜드 커뮤니케이션 스타일 추출
- 타겟 고객 (Target Customers): 주요/부차 타겟층, 연령대, 특성 분석
- 브랜드 컬러 (Brand Colors): 이미지 기반 컬러 팔레트 자동 추출
- 키워드 & 해시태그: SEO/SNS 최적화 키워드 자동 생성
- 시각적 스타일: 인테리어, 외관, 분위기, 추천 사진 스타일
- 차별화 포인트 (USP): 경쟁력 있는 고유 가치 제안
- DNACard 컴포넌트로 시각적 결과 표시
- 📸 스마트 이미지 크롤링 강화:
- 네이버 플레이스 이미지 최대 100장 크롤링 (v3.5.0에서 확대)
- 다양한 이미지 소스 수집 (menuImages, bizImages, roomImages, fsasImages)
- 이미지 셔플 및 중복 제거 알고리즘 적용
- 💾 펜션 이미지 영구 저장 시스템:
- 크롤링/업로드된 이미지를 펜션 프로필에 자동 저장
pension_images테이블로 이미지 메타데이터 관리- 펜션 선택 시 저장된 이미지 자동 로드
- 이미지 추가/삭제 API 엔드포인트
- 🎯 이미지 선택 UI 개선 (Beginner Mode):
- 전체 선택 / 개별 선택 / 랜덤 선택 모드
- 체크박스 기반 직관적 이미지 선택
- 선택된 이미지만으로 영상 생성
- 📊 API 엔드포인트 추가:
POST /api/profile/pension/:id/images- 이미지 저장GET /api/profile/pension/:id/images- 이미지 목록 조회DELETE /api/profile/pension/:id/images/:imageId- 이미지 삭제POST /api/gemini/analyze-dna- DNA 분석
v3.3.0 - UX Level System
- 🎯 사용자 레벨 시스템: 3단계 UX 레벨 도입
- 쌩초보 (Beginner): "다 알아서 해줘" - 최소한의 옵션, 원클릭 생성
- 중급 (Intermediate): "조금만 선택할게" - 장르/언어 선택, 기본 커스터마이징
- 프로 (Pro): "내가 다 컨트롤" - 모든 옵션 제어, 축제 연동
- 🤖 자동 업로드 시스템: 레벨에 따른 자동 업로드 제어
- Beginner/Intermediate: 강제 자동 업로드 (YouTube, Instagram, TikTok)
- Pro: 수동/자동 선택 가능
- AI 기반 SEO 데이터 자동 생성 (제목, 설명, 태그, 해시태그)
- ⏰ 주간 자동 생성 스케줄러: node-cron 기반 예약 생성
- 요일/시간 선택 가능
- 자동 큐 관리 및 순차 처리
- 실패 시 자동 재시도
- 🎨 조건부 UI 렌더링: 레벨에 따른 메뉴 및 옵션 표시
- Sidebar 메뉴 필터링
- NewProjectView 단계 간소화 (Beginner: 2단계, Pro: 4단계)
- SettingsView에 레벨 변경 UI 추가
- 📊 데이터베이스 확장:
experience_level컬럼 추가auto_generation_settings테이블 (자동 생성 설정)generation_queue테이블 (작업 큐)upload_history테이블 (업로드 이력)
v3.2.1 - Instagram Service & Admin Dashboard Fixes
- 🔧 Instagram 서비스 안정화:
- None 값 처리 개선 (
NoneTypehas no attributestrip에러 해결) - 디버그 로깅 추가로 문제 진단 용이
- instagrapi 라이브러리 2.1.2 → 2.2.1 업그레이드
- None 값 처리 개선 (
- 🚀 start.sh 개선:
- Python 캐시 자동 삭제 (
.pyc,__pycache__) - 코드 변경 시 서비스 재시작 없이 즉시 반영
- Python 캐시 자동 삭제 (
- 🛡️ AdminDashboard 권한 체크 수정:
- 사용자 정보 로딩 완료 후 권한 체크하도록 수정
- 관리자 로그인 후
/admin접근 시 리다이렉트 문제 해결
v3.2.0 - Festival Integration + Billing & Analytics
- 🎪 축제 연동 시스템: 한국관광공사 축제 데이터 통합
- 실시간 축제 정보 조회 및 자동 동기화
- 행정구역별 축제 그룹핑 (시/도 기준)
- 펜션 위치 기반 근처 축제 자동 추천
- 선택한 축제 정보가 영상 콘텐츠에 자동 반영
- 💰 Google Cloud Billing 연동: BigQuery 기반 실시간 비용 추적
- 서비스별/SKU별 비용 상세 분석
- 일별/월별 비용 트렌드 차트
- Gemini API 사용량 별도 집계
- USD/KRW 환율 자동 적용
- 📊 API 사용량 추적 시스템: 서비스별 사용량 모니터링
- Gemini, Suno, YouTube 등 서비스별 사용량 집계
- 사용자별 API 호출 추적 (과금 대비)
- 모델별 성공/실패율 및 평균 지연시간
- 월별 사용량 리포트 자동 생성
- 🎯 AI 모델 우선순위 Fallback 시스템: 지능적 모델 선택
- Gemini 2.0 Flash → Gemini 2.5 Flash → Imagen 3 자동 전환
- Rate Limit (429) 또는 서버 오류 (500) 시 자동 Fallback
- 모델별 비용 추정 및 최적화
- ✨ AI 매직 라이트: 펜션 컨셉 자동 생성
- 펜션 정보 + 카테고리 + 축제 정보 기반 AI 작문
- 2-3문장 매력적인 마케팅 컨셉 자동 생성
- 🔐 개별 YouTube OAuth 2.0: 사용자별 채널 연동 완성
- 각 사용자가 자신의 YouTube 채널 연결
- 연결된 채널로 직접 업로드
- 연결 상태 관리 및 토큰 자동 갱신
- 버그 수정:
- Gemini API 500 오류 시 모델 자동 전환
- YouTube 업로드 시 명확한 연결 상태 확인
- 축제 데이터 날짜 포맷 정규화
v3.1.0 - Custard Branding + Complete Manuals
- 커스터드(Custard) 브랜딩: 🍮 테마로 전체 리브랜딩
- CaStAD = Custard (카스타드) 철학 적용
- SVG 로고: 라메킨에 담긴 커스터드 푸딩 + 스팀 애니메이션
- 브랜드 스토리: 정밀함(달걀), 부드러움(우유), 달콤함(설탕)
- 컬러 팔레트: Custard Cream, Caramel Gold, Egg Yolk, Warm Amber
- 완전한 매뉴얼 시스템: 5개 역할별 매뉴얼 완비
- Part A: 개발자 매뉴얼
- Part B: 운용자 매뉴얼
- Part C: 사용자 매뉴얼
- Part D: 마케터 매뉴얼 (신규)
- Part E: 영업사원 매뉴얼 (신규)
- 버그 수정: AccountView 플랜 정보 동적 표시
v3.0.0 - TikTok + Advanced Analytics
- CaStAD 브랜딩: 새로운 로고 및 전체 사이트 리브랜딩
- TikTok 연동: OAuth 2.0 기반 TikTok Content Posting API 통합
- Direct Post / Inbox(Draft) 업로드 지원
- 업로드 히스토리 및 통계
- 고급 통계 시스템: 슈퍼어드민을 위한 종합 분석 대시보드
- 사용자 성장, 영상 트렌드, 플랫폼 업로드 통계
- 크레딧 사용 분석, 플랜 분포, 지역별 분포
- 수익 예측, 시스템 헬스 모니터링
- 영업용 매뉴얼: 영업 담당자를 위한 상세 판매 가이드
- 테스트 강화: 39개 API 엔드포인트 종합 테스트 (92% 통과율)
v2.2.0 - Asset Management & Plan System
- 에셋 관리 시스템: 사용자별 스토리지 할당 및 관리
- 구독 플랜 시스템: Free/Basic/Pro/Business 4단계 플랜
- 관리자 플랜 수정: 어드민에서 사용자별 플랜/크레딧 조정
- 자동 에셋 저장: 렌더링 시 생성된 모든 에셋 자동 저장
- 향상된 테스트: API 종합 테스트 스크립트 추가
v2.1.0 - Enhanced Authentication & i18n
- 소셜 로그인: Google/Naver OAuth 2.0 통합
- 이메일 인증: 회원가입 시 이메일 확인 필수
- 비밀번호 재설정: 이메일 기반 비밀번호 복구
- 완전한 i18n: UI 전체 6개 언어 지원
v2.0.0 - Multi-Pension & YouTube Integration
- 다중 펜션 관리: 1 계정 N 펜션 등록/관리
- YouTube OAuth 2.0: 사용자 채널 직접 연동
- 다국어 SEO: 6개 언어 자동 메타데이터 생성
v1.x - Foundation
- JWT 기반 인증 시스템
- SQLite 데이터베이스
- Puppeteer 서버사이드 렌더링
- Gemini 2.5 Flash 통합
🔗 기술 참고 링크
공식 문서
| 기술 | 링크 |
|---|---|
| React 19 | https://react.dev |
| Vite | https://vitejs.dev |
| Express.js | https://expressjs.com |
| Puppeteer | https://pptr.dev |
| FFmpeg | https://ffmpeg.org |
Google APIs
| API | 문서 링크 |
|---|---|
| Gemini API | https://ai.google.dev/docs |
| YouTube Data API | https://developers.google.com/youtube/v3 |
| OAuth 2.0 | https://developers.google.com/identity/protocols/oauth2 |
📜 라이선스
MIT License - 자유롭게 사용, 수정, 배포 가능
👥 Contributors
- waabaa - Lead Developer
© 2025 CaStAD Team. All Rights Reserved.