541 lines
10 KiB
Markdown
541 lines
10 KiB
Markdown
# O2Sound API Documentation
|
|
|
|
## 목차
|
|
1. [개요](#개요)
|
|
2. [인증](#인증)
|
|
3. [API 엔드포인트](#api-엔드포인트)
|
|
- [기본 엔드포인트](#기본-엔드포인트)
|
|
- [인증 API](#인증-api)
|
|
- [소셜 로그인 API](#소셜-로그인-api)
|
|
- [사용자 API](#사용자-api)
|
|
- [비디오 스트리밍 API](#비디오-스트리밍-api)
|
|
- [영상 제작 API](#영상-제작-api)
|
|
4. [에러 처리](#에러-처리)
|
|
5. [워크플로우 상세](#워크플로우-상세)
|
|
|
|
## 개요
|
|
|
|
### 기본 정보
|
|
- **Base URL**: `http://localhost:8000`
|
|
- **API Version**: v1
|
|
- **Framework**: FastAPI
|
|
- **Documentation**: `/docs` (Swagger UI), `/redoc` (ReDoc)
|
|
|
|
### 기술 스택
|
|
- **백엔드 프레임워크**: FastAPI
|
|
- **비동기 작업 처리**: Celery
|
|
- **메시지 브로커**: Redis
|
|
- **데이터베이스**: PostgreSQL (추정)
|
|
- **인증**: Session-based + OAuth 2.0 (Google)
|
|
|
|
### 응답 형식
|
|
모든 API 응답은 `@response_wrapper` 데코레이터를 통해 일관된 형식으로 반환됩니다.
|
|
|
|
## 인증
|
|
|
|
### 세션 기반 인증
|
|
- 로그인 후 세션 쿠키를 통한 인증
|
|
- SessionMiddleware 사용
|
|
|
|
### OAuth 2.0
|
|
- Google OAuth 지원
|
|
- 임시 토큰을 통한 안전한 토큰 교환
|
|
|
|
## API 엔드포인트
|
|
|
|
### 기본 엔드포인트
|
|
|
|
#### 서비스 정보 확인
|
|
```http
|
|
GET /
|
|
```
|
|
|
|
**응답 예시:**
|
|
```json
|
|
{
|
|
"message": "FastAPI DDD with Celery Workers",
|
|
"version": "1.0.0",
|
|
"docs": "/docs"
|
|
}
|
|
```
|
|
|
|
#### 헬스 체크
|
|
```http
|
|
GET /health
|
|
```
|
|
|
|
**응답 예시:**
|
|
```json
|
|
{
|
|
"status": "healthy",
|
|
"database": "connected",
|
|
"redis": "connected",
|
|
"celery": "running"
|
|
}
|
|
```
|
|
|
|
### 인증 API
|
|
|
|
#### 회원가입
|
|
```http
|
|
POST /auth/join
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**요청 본문:**
|
|
```json
|
|
{
|
|
"user_id": "testuser",
|
|
"name": "홍길동",
|
|
"password": "securepassword123",
|
|
"email": "test@example.com",
|
|
"phone_number": "010-1234-5678"
|
|
}
|
|
```
|
|
|
|
**응답 (201 Created):**
|
|
```json
|
|
{
|
|
"id": "123e4567-e89b-12d3-a456-426614174000",
|
|
"name": "홍길동"
|
|
}
|
|
```
|
|
|
|
#### 로그인
|
|
```http
|
|
POST /auth/login
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**요청 본문:**
|
|
```json
|
|
{
|
|
"user_id": "testuser",
|
|
"password": "securepassword123"
|
|
}
|
|
```
|
|
|
|
**응답 (200 OK):**
|
|
```json
|
|
{
|
|
"id": "123e4567-e89b-12d3-a456-426614174000",
|
|
"name": "홍길동"
|
|
}
|
|
```
|
|
|
|
### 소셜 로그인 API
|
|
|
|
#### Google OAuth 로그인 시작
|
|
```http
|
|
GET /social/google/login?return_url=http://localhost:3300/dashboard
|
|
```
|
|
|
|
**쿼리 파라미터:**
|
|
- `return_url` (선택): 로그인 성공 후 리다이렉트할 URL
|
|
|
|
**응답:**
|
|
- Google OAuth 인증 페이지로 302 리다이렉트
|
|
|
|
#### Google OAuth 콜백
|
|
```http
|
|
GET /social/google/callback?code=AUTHORIZATION_CODE&state=STATE
|
|
```
|
|
|
|
**쿼리 파라미터:**
|
|
- `code`: Google에서 제공한 인증 코드
|
|
- `state`: CSRF 방지를 위한 상태 값
|
|
- `error` (선택): OAuth 에러 발생 시
|
|
|
|
**응답:**
|
|
- 성공: `{return_url}?token={temp_token_id}&auth_success=true`로 리다이렉트
|
|
- 실패: `http://localhost:3300/auth/error?error={error_message}`로 리다이렉트
|
|
|
|
#### Google 토큰 정보 조회
|
|
```http
|
|
GET /social/google/token/{temp_token_id}
|
|
```
|
|
|
|
**경로 파라미터:**
|
|
- `temp_token_id`: 임시 토큰 ID
|
|
|
|
**응답 (200 OK):**
|
|
```json
|
|
{
|
|
"access_token": "ya29.a0AfH6SMBx...",
|
|
"refresh_token": "1//0gVO1VQ...",
|
|
"token_type": "Bearer",
|
|
"expires_in": 3599,
|
|
"user_info": {
|
|
"id": "google_user_id",
|
|
"email": "user@gmail.com",
|
|
"name": "사용자 이름",
|
|
"picture": "https://lh3.googleusercontent.com/..."
|
|
}
|
|
}
|
|
```
|
|
|
|
### 사용자 API
|
|
|
|
#### 사용자 업체 목록 조회
|
|
```http
|
|
POST /user/items
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**요청 본문:**
|
|
```json
|
|
{
|
|
"id": "123e4567-e89b-12d3-a456-426614174000"
|
|
}
|
|
```
|
|
|
|
**응답 (200 OK):**
|
|
```json
|
|
{
|
|
"total_count": 2,
|
|
"items": [
|
|
{
|
|
"item_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"name": "카페 블루문",
|
|
"address": "서울시 강남구 역삼동 123-45",
|
|
"url": "https://bluemoon.cafe",
|
|
"phone_number": "02-1234-5678",
|
|
"thumbnail_url": "https://example.com/thumb1.jpg",
|
|
"hashtags": ["카페", "브런치", "디저트"]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### 업체 정보 수정
|
|
```http
|
|
PUT /user/item/update
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**요청 본문:**
|
|
```json
|
|
{
|
|
"id": "123e4567-e89b-12d3-a456-426614174000",
|
|
"item_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"name": "카페 블루문 강남점",
|
|
"address": "서울시 강남구 역삼동 123-45",
|
|
"url": "https://bluemoon-gangnam.cafe",
|
|
"phone_number": "02-1234-5678",
|
|
"thumbnail_url": "https://example.com/new-thumb.jpg"
|
|
}
|
|
```
|
|
|
|
**응답 (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"item_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
#### 업체 삭제
|
|
```http
|
|
DELETE /user/item/delete
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**요청 본문:**
|
|
```json
|
|
{
|
|
"id": "123e4567-e89b-12d3-a456-426614174000",
|
|
"item_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
**응답 (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"item_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
#### 사용자 비디오 목록 조회
|
|
```http
|
|
POST /user/videos
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**요청 본문:**
|
|
```json
|
|
{
|
|
"id": "123e4567-e89b-12d3-a456-426614174000"
|
|
}
|
|
```
|
|
|
|
**응답 (200 OK):**
|
|
```json
|
|
{
|
|
"total_count": 3,
|
|
"videos": [
|
|
{
|
|
"id": "660e8400-e29b-41d4-a716-446655440000",
|
|
"title": "카페 블루문 홍보 영상",
|
|
"description": "아늑한 분위기의 카페 블루문을 소개합니다",
|
|
"url": "/user/video/bluemoon_promo_2024.mp4",
|
|
"is_uploaded": true,
|
|
"download_count": 15,
|
|
"resolution": "1920x1080",
|
|
"status": "completed",
|
|
"thumbnail_url": "https://example.com/video-thumb1.jpg"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### 비디오 삭제
|
|
```http
|
|
DELETE /user/video/delete
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**요청 본문:**
|
|
```json
|
|
{
|
|
"user_id": "testuser",
|
|
"video_id": "660e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
**응답 (200 OK):**
|
|
```json
|
|
{
|
|
"message": "비디오가 성공적으로 삭제되었습니다"
|
|
}
|
|
```
|
|
|
|
#### 사용자 프로필 조회
|
|
```http
|
|
POST /user/profile
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**요청 본문:**
|
|
```json
|
|
{
|
|
"id": "123e4567-e89b-12d3-a456-426614174000"
|
|
}
|
|
```
|
|
|
|
**응답 (200 OK):**
|
|
```json
|
|
{
|
|
"id": "123e4567-e89b-12d3-a456-426614174000",
|
|
"name": "홍길동",
|
|
"email": "test@example.com",
|
|
"phone_number": "010-1234-5678",
|
|
"created_at": "2024-01-15T10:30:00Z"
|
|
}
|
|
```
|
|
|
|
#### 프로필 수정
|
|
```http
|
|
PUT /user/profile/update
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**요청 본문:**
|
|
```json
|
|
{
|
|
"id": "123e4567-e89b-12d3-a456-426614174000",
|
|
"name": "홍길동",
|
|
"email": "newemail@example.com",
|
|
"phone_number": "010-9876-5432"
|
|
}
|
|
```
|
|
|
|
**응답 (200 OK):**
|
|
```json
|
|
{
|
|
"user_id": "testuser",
|
|
"name": "홍길동"
|
|
}
|
|
```
|
|
|
|
### 비디오 스트리밍 API
|
|
|
|
#### 비디오 파일 스트리밍
|
|
```http
|
|
GET /user/video/{filename}
|
|
```
|
|
|
|
**경로 파라미터:**
|
|
- `filename`: 비디오 파일명 (URL 인코딩 지원)
|
|
|
|
**예시:**
|
|
```http
|
|
GET /user/video/bluemoon_promo_2024.mp4
|
|
```
|
|
|
|
**응답:**
|
|
- Content-Type: `video/mp4`
|
|
- 비디오 파일 스트리밍
|
|
|
|
**에러 응답 (404 Not Found):**
|
|
```json
|
|
{
|
|
"detail": "Video not found"
|
|
}
|
|
```
|
|
|
|
### 영상 제작 API
|
|
|
|
#### 영상 제작 워크플로우 시작
|
|
```http
|
|
POST /moviemaker/start-workflow
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**요청 본문:**
|
|
```json
|
|
{
|
|
"url": "https://bluemoon.cafe"
|
|
}
|
|
```
|
|
|
|
**응답 (200 OK):**
|
|
```json
|
|
{
|
|
"task_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
|
"progress": {
|
|
"metadata": false,
|
|
"lyrics": false,
|
|
"songs": false,
|
|
"images": false,
|
|
"movies": false,
|
|
"combined": false
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 워크플로우 진행률 확인
|
|
```http
|
|
POST /moviemaker/progress
|
|
Content-Type: application/json
|
|
```
|
|
|
|
**요청 본문:**
|
|
```json
|
|
{
|
|
"task_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
|
|
}
|
|
```
|
|
|
|
**응답 (200 OK):**
|
|
```json
|
|
{
|
|
"progress": {
|
|
"metadata": true,
|
|
"lyrics": true,
|
|
"songs": true,
|
|
"images": false,
|
|
"movies": false,
|
|
"combined": false
|
|
}
|
|
}
|
|
```
|
|
|
|
## 에러 처리
|
|
|
|
### 표준 에러 응답 형식
|
|
```json
|
|
{
|
|
"error_code": "ERROR_CODE",
|
|
"error_message": "사용자 친화적인 에러 메시지"
|
|
}
|
|
```
|
|
|
|
### 일반적인 HTTP 상태 코드
|
|
- `200 OK`: 요청 성공
|
|
- `201 Created`: 리소스 생성 성공
|
|
- `400 Bad Request`: 잘못된 요청
|
|
- `401 Unauthorized`: 인증 필요
|
|
- `403 Forbidden`: 권한 없음
|
|
- `404 Not Found`: 리소스를 찾을 수 없음
|
|
- `422 Unprocessable Entity`: 유효성 검사 실패
|
|
- `500 Internal Server Error`: 서버 오류
|
|
|
|
### 에러 코드 예시
|
|
- `AUTH_001`: 잘못된 로그인 정보
|
|
- `AUTH_002`: 이미 존재하는 사용자 ID
|
|
- `USER_001`: 사용자를 찾을 수 없음
|
|
- `VIDEO_001`: 비디오를 찾을 수 없음
|
|
- `TASK_001`: 작업을 찾을 수 없음
|
|
|
|
## 워크플로우 상세
|
|
|
|
### 영상 제작 프로세스
|
|
|
|
1. **URL 크롤링 (task1_crawl)**
|
|
- 입력 URL에서 메타데이터 추출
|
|
- 업체명, 설명, 키워드 등 수집
|
|
|
|
2. **병렬 처리**
|
|
|
|
**가사 및 음악 생성 브랜치:**
|
|
- **가사 생성 (task2_generate_lyrics)**
|
|
- 크롤링한 메타데이터 기반 가사 생성
|
|
- AI 모델을 통한 창의적인 가사 작성
|
|
|
|
- **음악 생성 (task3_generate_music)**
|
|
- 생성된 가사에 맞는 음악 제작
|
|
- 장르, 템포, 분위기 자동 매칭
|
|
|
|
**이미지 및 비디오 생성 브랜치:**
|
|
- **이미지 크롤링 (task1_crawl_images)**
|
|
- 웹사이트에서 관련 이미지 수집
|
|
- 품질 및 관련성 필터링
|
|
|
|
- **비디오 생성 (task4_generate_video)**
|
|
- 수집된 이미지로 비디오 제작
|
|
- 전환 효과 및 애니메이션 적용
|
|
|
|
3. **최종 병합 (task5_merge_results)**
|
|
- 음악과 비디오 동기화
|
|
- 최종 영상 파일 생성
|
|
- 업로드 및 저장
|
|
|
|
### 진행률 추적
|
|
- Redis를 통한 실시간 상태 업데이트
|
|
- 각 단계별 완료 상태 확인 가능
|
|
- 비동기 작업으로 긴 처리 시간 대응
|
|
|
|
## 개발 가이드
|
|
|
|
### 로컬 개발 환경 실행
|
|
```bash
|
|
# Poetry 환경 설정
|
|
poetry install
|
|
|
|
# 환경 변수 설정
|
|
cp .env.local .env
|
|
|
|
# Redis 실행 (Docker)
|
|
docker run -d -p 6379:6379 redis
|
|
|
|
# Celery Worker 실행
|
|
./run-celery.sh
|
|
|
|
# FastAPI 서버 실행
|
|
./run-local.sh
|
|
```
|
|
|
|
### API 테스트
|
|
- Swagger UI: `http://localhost:8000/docs`
|
|
- ReDoc: `http://localhost:8000/redoc`
|
|
|
|
### 프로덕션 배포
|
|
```bash
|
|
# Docker 이미지 빌드
|
|
docker build -t o2sound-backend .
|
|
|
|
# 프로덕션 실행
|
|
./run-prod.sh
|
|
```
|