{ "info": { "title": "Social Media Integration API", "version": "1.0.0", "description": "소셜 미디어 연동 및 영상 업로드 API 명세서", "baseUrl": "http://localhost:8000" }, "authentication": { "type": "Bearer Token", "header": "Authorization", "format": "Bearer {access_token}", "description": "카카오 로그인 후 발급받은 JWT access_token 사용" }, "endpoints": { "oauth": { "connect": { "name": "소셜 계정 연동 시작", "method": "GET", "url": "/social/oauth/{platform}/connect", "description": "OAuth 인증 URL을 생성합니다. 반환된 auth_url로 사용자를 리다이렉트하세요.", "authentication": true, "pathParameters": { "platform": { "type": "string", "enum": ["youtube"], "description": "연동할 플랫폼 (현재 youtube만 지원)" } }, "request": { "headers": { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } }, "response": { "success": { "status": 200, "body": { "auth_url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=xxx&redirect_uri=xxx&response_type=code&scope=xxx&state=xxx", "state": "abc123xyz789", "platform": "youtube" } }, "error": { "401": { "detail": "인증이 필요합니다." }, "422": { "detail": "지원하지 않는 플랫폼입니다." } } }, "frontendAction": "auth_url로 window.location.href 또는 새 창으로 리다이렉트" }, "callback": { "name": "OAuth 콜백 (백엔드 자동 처리)", "method": "GET", "url": "/social/oauth/{platform}/callback", "description": "Google에서 자동으로 호출됩니다. 프론트엔드에서 직접 호출하지 마세요.", "authentication": false, "note": "연동 성공 시 프론트엔드의 /social/connect/success 페이지로 리다이렉트됩니다.", "redirectOnSuccess": { "url": "{PROJECT_DOMAIN}/social/connect/success", "queryParams": { "platform": "youtube", "account_id": 1 } }, "redirectOnError": { "url": "{PROJECT_DOMAIN}/social/connect/error", "queryParams": { "platform": "youtube", "error": "에러 메시지" } } }, "getAccounts": { "name": "연동된 계정 목록 조회", "method": "GET", "url": "/social/oauth/accounts", "description": "현재 사용자가 연동한 모든 소셜 계정 목록을 반환합니다.", "authentication": true, "request": { "headers": { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } }, "response": { "success": { "status": 200, "body": { "accounts": [ { "id": 1, "platform": "youtube", "platform_user_id": "UC1234567890abcdef", "platform_username": "@mychannel", "display_name": "My YouTube Channel", "profile_image_url": "https://yt3.ggpht.com/...", "is_active": true, "connected_at": "2024-01-15T12:00:00", "platform_data": { "channel_id": "UC1234567890abcdef", "channel_title": "My YouTube Channel", "subscriber_count": "1000", "video_count": "50" } } ], "total": 1 } } } }, "getAccountByPlatform": { "name": "특정 플랫폼 연동 계정 조회", "method": "GET", "url": "/social/oauth/accounts/{platform}", "description": "특정 플랫폼에 연동된 계정 정보를 반환합니다.", "authentication": true, "pathParameters": { "platform": { "type": "string", "enum": ["youtube"], "description": "조회할 플랫폼" } }, "request": { "headers": { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } }, "response": { "success": { "status": 200, "body": { "id": 1, "platform": "youtube", "platform_user_id": "UC1234567890abcdef", "platform_username": "@mychannel", "display_name": "My YouTube Channel", "profile_image_url": "https://yt3.ggpht.com/...", "is_active": true, "connected_at": "2024-01-15T12:00:00", "platform_data": { "channel_id": "UC1234567890abcdef", "channel_title": "My YouTube Channel", "subscriber_count": "1000", "video_count": "50" } } }, "error": { "404": { "detail": "youtube 플랫폼에 연동된 계정이 없습니다." } } } }, "disconnect": { "name": "소셜 계정 연동 해제", "method": "DELETE", "url": "/social/oauth/{platform}/disconnect", "description": "소셜 미디어 계정 연동을 해제합니다.", "authentication": true, "pathParameters": { "platform": { "type": "string", "enum": ["youtube"], "description": "연동 해제할 플랫폼" } }, "request": { "headers": { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } }, "response": { "success": { "status": 200, "body": { "success": true, "message": "youtube 계정 연동이 해제되었습니다." } }, "error": { "404": { "detail": "youtube 플랫폼에 연동된 계정이 없습니다." } } } } }, "upload": { "create": { "name": "소셜 플랫폼에 영상 업로드 요청", "method": "POST", "url": "/social/upload", "description": "영상을 소셜 미디어 플랫폼에 업로드합니다. 백그라운드에서 처리됩니다.", "authentication": true, "request": { "headers": { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "Content-Type": "application/json" }, "body": { "video_id": { "type": "integer", "required": true, "description": "업로드할 영상 ID (Video 테이블의 id)", "example": 123 }, "platform": { "type": "string", "required": true, "enum": ["youtube"], "description": "업로드할 플랫폼", "example": "youtube" }, "title": { "type": "string", "required": true, "maxLength": 100, "description": "영상 제목", "example": "나의 첫 영상" }, "description": { "type": "string", "required": false, "maxLength": 5000, "description": "영상 설명", "example": "이 영상은 테스트 영상입니다." }, "tags": { "type": "array", "required": false, "items": "string", "description": "태그 목록", "example": ["여행", "vlog", "일상"] }, "privacy_status": { "type": "string", "required": false, "enum": ["public", "unlisted", "private"], "default": "private", "description": "공개 상태", "example": "private" }, "platform_options": { "type": "object", "required": false, "description": "플랫폼별 추가 옵션", "example": { "category_id": "22" } } }, "example": { "video_id": 123, "platform": "youtube", "title": "나의 첫 영상", "description": "이 영상은 테스트 영상입니다.", "tags": ["여행", "vlog"], "privacy_status": "private", "platform_options": { "category_id": "22" } } }, "response": { "success": { "status": 200, "body": { "success": true, "upload_id": 456, "platform": "youtube", "status": "pending", "message": "업로드 요청이 접수되었습니다." } }, "error": { "404_video": { "detail": "영상을 찾을 수 없습니다." }, "404_account": { "detail": "youtube 플랫폼에 연동된 계정이 없습니다." }, "400": { "detail": "영상이 아직 준비되지 않았습니다." } } }, "youtubeCategoryIds": { "1": "Film & Animation", "2": "Autos & Vehicles", "10": "Music", "15": "Pets & Animals", "17": "Sports", "19": "Travel & Events", "20": "Gaming", "22": "People & Blogs (기본값)", "23": "Comedy", "24": "Entertainment", "25": "News & Politics", "26": "Howto & Style", "27": "Education", "28": "Science & Technology", "29": "Nonprofits & Activism" } }, "getStatus": { "name": "업로드 상태 조회", "method": "GET", "url": "/social/upload/{upload_id}/status", "description": "특정 업로드 작업의 상태를 조회합니다. 폴링으로 상태를 확인하세요.", "authentication": true, "pathParameters": { "upload_id": { "type": "integer", "description": "업로드 ID" } }, "request": { "headers": { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } }, "response": { "success": { "status": 200, "body": { "upload_id": 456, "video_id": 123, "platform": "youtube", "status": "completed", "upload_progress": 100, "title": "나의 첫 영상", "platform_video_id": "dQw4w9WgXcQ", "platform_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "error_message": null, "retry_count": 0, "created_at": "2024-01-15T12:00:00", "uploaded_at": "2024-01-15T12:05:00" } }, "error": { "404": { "detail": "업로드 정보를 찾을 수 없습니다." } } }, "statusValues": { "pending": "업로드 대기 중", "uploading": "업로드 진행 중 (upload_progress 확인)", "processing": "플랫폼에서 처리 중", "completed": "업로드 완료 (platform_url 사용 가능)", "failed": "업로드 실패 (error_message 확인)", "cancelled": "업로드 취소됨" }, "pollingRecommendation": { "interval": "3초", "maxAttempts": 100, "stopConditions": ["completed", "failed", "cancelled"] } }, "getHistory": { "name": "업로드 이력 조회", "method": "GET", "url": "/social/upload/history", "description": "사용자의 소셜 미디어 업로드 이력을 조회합니다.", "authentication": true, "queryParameters": { "platform": { "type": "string", "required": false, "enum": ["youtube"], "description": "플랫폼 필터" }, "status": { "type": "string", "required": false, "enum": ["pending", "uploading", "processing", "completed", "failed", "cancelled"], "description": "상태 필터" }, "page": { "type": "integer", "required": false, "default": 1, "description": "페이지 번호" }, "size": { "type": "integer", "required": false, "default": 20, "min": 1, "max": 100, "description": "페이지 크기" } }, "request": { "headers": { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }, "exampleUrl": "/social/upload/history?platform=youtube&status=completed&page=1&size=20" }, "response": { "success": { "status": 200, "body": { "items": [ { "upload_id": 456, "video_id": 123, "platform": "youtube", "status": "completed", "title": "나의 첫 영상", "platform_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "created_at": "2024-01-15T12:00:00", "uploaded_at": "2024-01-15T12:05:00" } ], "total": 1, "page": 1, "size": 20 } } } }, "retry": { "name": "업로드 재시도", "method": "POST", "url": "/social/upload/{upload_id}/retry", "description": "실패한 업로드를 재시도합니다.", "authentication": true, "pathParameters": { "upload_id": { "type": "integer", "description": "업로드 ID" } }, "request": { "headers": { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } }, "response": { "success": { "status": 200, "body": { "success": true, "upload_id": 456, "platform": "youtube", "status": "pending", "message": "업로드 재시도가 요청되었습니다." } }, "error": { "400": { "detail": "실패하거나 취소된 업로드만 재시도할 수 있습니다." }, "404": { "detail": "업로드 정보를 찾을 수 없습니다." } } } }, "cancel": { "name": "업로드 취소", "method": "DELETE", "url": "/social/upload/{upload_id}", "description": "대기 중인 업로드를 취소합니다.", "authentication": true, "pathParameters": { "upload_id": { "type": "integer", "description": "업로드 ID" } }, "request": { "headers": { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } }, "response": { "success": { "status": 200, "body": { "success": true, "message": "업로드가 취소되었습니다." } }, "error": { "400": { "detail": "대기 중인 업로드만 취소할 수 있습니다." }, "404": { "detail": "업로드 정보를 찾을 수 없습니다." } } } } } }, "frontendPages": { "required": [ { "path": "/social/connect/success", "description": "OAuth 연동 성공 후 리다이렉트되는 페이지", "queryParams": ["platform", "account_id"], "action": "연동 성공 메시지 표시 후 설정 페이지로 이동" }, { "path": "/social/connect/error", "description": "OAuth 연동 실패 시 리다이렉트되는 페이지", "queryParams": ["platform", "error"], "action": "에러 메시지 표시 및 재시도 옵션 제공" } ], "recommended": [ { "path": "/settings/social", "description": "소셜 계정 관리 페이지", "features": ["연동된 계정 목록", "연동/해제 버튼", "업로드 이력"] } ] }, "flowExamples": { "connectYouTube": { "description": "YouTube 계정 연동 플로우", "steps": [ { "step": 1, "action": "GET /social/oauth/youtube/connect 호출", "result": "auth_url 반환" }, { "step": 2, "action": "window.location.href = auth_url", "result": "Google 로그인 페이지로 이동" }, { "step": 3, "action": "사용자가 권한 승인", "result": "백엔드 콜백 URL로 자동 리다이렉트" }, { "step": 4, "action": "백엔드가 토큰 교환 후 프론트엔드로 리다이렉트", "result": "/social/connect/success?platform=youtube&account_id=1" }, { "step": 5, "action": "연동 성공 처리 후 GET /social/oauth/accounts 호출", "result": "연동된 계정 정보 표시" } ] }, "uploadVideo": { "description": "YouTube 영상 업로드 플로우", "steps": [ { "step": 1, "action": "POST /social/upload 호출", "request": { "video_id": 123, "platform": "youtube", "title": "영상 제목", "privacy_status": "private" }, "result": "upload_id 반환" }, { "step": 2, "action": "GET /social/upload/{upload_id}/status 폴링 (3초 간격)", "result": "status, upload_progress 확인" }, { "step": 3, "action": "status === 'completed' 확인", "result": "platform_url로 YouTube 링크 표시" } ], "pollingCode": "setInterval(() => checkUploadStatus(uploadId), 3000)" } } }