Files
drama-studio/.claude/project-knowledge.md
jungwoo choi cc547372c0 feat: Drama Studio 프로젝트 초기 구조 설정
- FastAPI 백엔드 (audio-studio-api)
- Next.js 프론트엔드 (audio-studio-ui)
- Qwen3-TTS 엔진 (audio-studio-tts)
- MusicGen 서비스 (audio-studio-musicgen)
- Docker Compose 개발/운영 환경

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 11:39:38 +09:00

7.9 KiB

Project Knowledge

이 문서는 프로젝트의 개발 표준 및 패턴을 정의합니다. Claude.ai Projects 또는 Claude Code에서 참조하여 일관된 코드를 작성하세요.


1. 프로젝트 개요

기술 스택

  • Frontend: Next.js 16 + React 19 + TypeScript + Tailwind CSS 4 + shadcn/ui
  • Backend: FastAPI + Python 3.11 + Pydantic v2
  • Database: MongoDB 7.0 (motor async driver) + Redis 7
  • AI: Claude API (Anthropic) + OpenAI API
  • Containerization: Docker + Docker Compose
  • Repository: Gitea (http://gitea.yakenator.io/yakenator/)

2. Docker 배포 규칙

Dockerfile 패턴 (Python Worker)

FROM python:3.11-slim
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends git && rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY *.py .
CMD ["python", "worker.py"]

docker-compose 서비스 패턴

services:
  {서비스명}:
    build:
      context: ./repos/{서비스명}
      dockerfile: Dockerfile
    container_name: {프로젝트}-{서비스명}
    restart: unless-stopped
    environment:
      - REDIS_URL=redis://redis:6379
      - MONGODB_URL=mongodb://${MONGO_USER}:${MONGO_PASSWORD}@mongodb:27017/
      - DB_NAME={데이터베이스명}
    depends_on:
      redis:
        condition: service_healthy
      mongodb:
        condition: service_healthy
    networks:
      - {프로젝트}-network

네이밍 규칙

  • 컨테이너: {프로젝트}-{서비스명}
  • 볼륨: {프로젝트}_{데이터유형}_data
  • 네트워크: {프로젝트}-network

3. 한국어 개발 컨벤션

Docstring

async def get_data(self, name: str, context: List[str] = None) -> DataInfo:
    """
    데이터 조회 (context 기반 후보 선택)

    Args:
        name: 데이터 이름
        context: 컨텍스트 키워드

    Returns:
        DataInfo 객체
    """

로깅 메시지 (한글 + 영문 혼용)

logger.info(f"Found {len(items)} item(s) for '{name}'")
logger.warning(f"Operation failed (non-critical): {e}")

커밋 메시지

feat: 기능 설명

- 변경사항 1
- 변경사항 2

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

4. FastAPI 패턴

앱 초기화

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI(
    title="{서비스명} API",
    description="서비스 설명",
    version="1.0.0"
)

Pydantic 모델

class CreateRequest(BaseModel):
    name: str
    description: Optional[str] = ""
    data_type: Optional[str] = "default"

엔드포인트

@app.get("/health")
async def health_check():
    return {"status": "healthy", "timestamp": datetime.now().isoformat()}

@app.post("/create")
async def create_item(request: CreateRequest):
    try:
        # 처리 로직
        return {"success": True, "data": result}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

5. React/Next.js 패턴

디렉토리 구조

src/
├── app/                    # Next.js App Router
├── components/
│   ├── ui/                 # shadcn/ui 컴포넌트
│   └── providers.tsx       # Context Providers
├── hooks/                  # 커스텀 훅
├── lib/utils.ts            # cn() 등 유틸리티
└── types/                  # TypeScript 타입

cn() 유틸리티

import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

폼 패턴 (react-hook-form + zod)

const formSchema = z.object({
  title: z.string().min(1, "제목을 입력하세요"),
  content: z.string().min(10, "내용은 10자 이상"),
})

const form = useForm<z.infer<typeof formSchema>>({
  resolver: zodResolver(formSchema),
})

6. MongoDB 패턴

연결 (motor async)

from motor.motor_asyncio import AsyncIOMotorClient

client = AsyncIOMotorClient(os.getenv("MONGODB_URL"))
db = client[os.getenv("DB_NAME")]

인덱스 생성

await collection.create_index("unique_field", unique=True, sparse=True)
await collection.create_index("name")
await collection.create_index("updated_at")

Upsert 패턴

result = await collection.update_one(
    {"unique_field": data["unique_field"]},
    {
        "$set": update_doc,
        "$setOnInsert": {"created_at": datetime.now()}
    },
    upsert=True
)

TTL 캐시

CACHE_TTL_DAYS = 7

def _is_cache_fresh(self, cached_data: Dict) -> bool:
    updated_at = cached_data.get("updated_at")
    expiry_date = updated_at + timedelta(days=CACHE_TTL_DAYS)
    return datetime.now() < expiry_date

7. AI API 통합

Claude API

from anthropic import AsyncAnthropic

client = AsyncAnthropic(api_key=os.getenv("CLAUDE_API_KEY"))

response = await client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=8192,
    messages=[{"role": "user", "content": prompt}]
)

프롬프트 템플릿 (MongoDB 저장)

async def _get_prompt_template(self) -> str:
    # 캐시 확인
    if self._cached_prompt and time.time() - self._prompt_cache_time < 300:
        return self._cached_prompt

    # DB에서 조회
    custom_prompt = await self.db.prompts.find_one({"service": "{서비스명}"})
    return custom_prompt.get("content") if custom_prompt else self._default_prompt

8. 환경 변수

# .env
MONGO_USER=admin
MONGO_PASSWORD={비밀번호}
REDIS_URL=redis://redis:6379
CLAUDE_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-...
JWT_SECRET_KEY={시크릿키}
DB_NAME={데이터베이스명}

9. 헬스체크

FastAPI

@app.get("/health")
async def health():
    return {"status": "healthy"}

Docker Compose

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
  interval: 30s
  timeout: 10s
  retries: 3

10. 데이터베이스 백업 정책

백업 규칙

  • 주기: 하루에 한 번 (daily)
  • 보관 기간: 최소 7일
  • 백업 위치: 프로젝트 루트의 ./backups/ 디렉토리

MongoDB 백업 명령어

BACKUP_NAME="mongodb_backup_$(date +%Y%m%d_%H%M%S)"
docker exec {프로젝트}-mongodb mongodump \
    --uri="mongodb://{user}:{password}@localhost:27017" \
    --authenticationDatabase=admin \
    --out="/tmp/$BACKUP_NAME"
docker cp {프로젝트}-mongodb:/tmp/$BACKUP_NAME ./backups/

복원 명령어

docker cp ./backups/$BACKUP_NAME {프로젝트}-mongodb:/tmp/
docker exec {프로젝트}-mongodb mongorestore \
    --uri="mongodb://{user}:{password}@localhost:27017" \
    --authenticationDatabase=admin \
    "/tmp/$BACKUP_NAME"

자동화 (cron)

# crontab -e
0 2 * * * /path/to/backup-script.sh  # 매일 새벽 2시

주의사항

  • 새 프로젝트 생성 시 반드시 백업 스크립트 설정
  • 백업 디렉토리는 .gitignore에 추가
  • 중요 데이터는 외부 스토리지에 추가 백업 권장

11. Gitea 리포지토리 관리

서버 정보

새 리포지토리 생성 (API)

curl -X POST "http://gitea.yakenator.io/api/v1/user/repos" \
  -H "Content-Type: application/json" \
  -u "yakenator:asdfg23we" \
  -d '{"name": "{repo-name}", "private": false}'

새 프로젝트 초기화 및 푸시

# 1. Git 초기화
git init

# 2. 첫 커밋
git add -A
git commit -m "Initial commit"

# 3. Gitea에 리포지토리 생성 (위 API 사용)

# 4. Remote 추가 및 푸시
git remote add origin http://yakenator:asdfg23we@gitea.yakenator.io/yakenator/{repo-name}.git
git branch -M main
git push -u origin main

이 문서를 Claude.ai Projects의 "Project Knowledge"에 추가하면 프로젝트 컨텍스트를 공유할 수 있습니다.