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

353 lines
7.9 KiB
Markdown

# 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)
```dockerfile
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 서비스 패턴
```yaml
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
```python
async def get_data(self, name: str, context: List[str] = None) -> DataInfo:
"""
데이터 조회 (context 기반 후보 선택)
Args:
name: 데이터 이름
context: 컨텍스트 키워드
Returns:
DataInfo 객체
"""
```
### 로깅 메시지 (한글 + 영문 혼용)
```python
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 패턴
### 앱 초기화
```python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI(
title="{서비스명} API",
description="서비스 설명",
version="1.0.0"
)
```
### Pydantic 모델
```python
class CreateRequest(BaseModel):
name: str
description: Optional[str] = ""
data_type: Optional[str] = "default"
```
### 엔드포인트
```python
@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() 유틸리티
```typescript
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
```
### 폼 패턴 (react-hook-form + zod)
```typescript
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)
```python
from motor.motor_asyncio import AsyncIOMotorClient
client = AsyncIOMotorClient(os.getenv("MONGODB_URL"))
db = client[os.getenv("DB_NAME")]
```
### 인덱스 생성
```python
await collection.create_index("unique_field", unique=True, sparse=True)
await collection.create_index("name")
await collection.create_index("updated_at")
```
### Upsert 패턴
```python
result = await collection.update_one(
{"unique_field": data["unique_field"]},
{
"$set": update_doc,
"$setOnInsert": {"created_at": datetime.now()}
},
upsert=True
)
```
### TTL 캐시
```python
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
```python
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 저장)
```python
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. 환경 변수
```bash
# .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
```python
@app.get("/health")
async def health():
return {"status": "healthy"}
```
### Docker Compose
```yaml
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
```
---
## 10. 데이터베이스 백업 정책
### 백업 규칙
- **주기**: 하루에 한 번 (daily)
- **보관 기간**: 최소 7일
- **백업 위치**: 프로젝트 루트의 `./backups/` 디렉토리
### MongoDB 백업 명령어
```bash
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/
```
### 복원 명령어
```bash
docker cp ./backups/$BACKUP_NAME {프로젝트}-mongodb:/tmp/
docker exec {프로젝트}-mongodb mongorestore \
--uri="mongodb://{user}:{password}@localhost:27017" \
--authenticationDatabase=admin \
"/tmp/$BACKUP_NAME"
```
### 자동화 (cron)
```bash
# crontab -e
0 2 * * * /path/to/backup-script.sh # 매일 새벽 2시
```
### 주의사항
- 새 프로젝트 생성 시 반드시 백업 스크립트 설정
- 백업 디렉토리는 .gitignore에 추가
- 중요 데이터는 외부 스토리지에 추가 백업 권장
---
## 11. Gitea 리포지토리 관리
### 서버 정보
- **URL**: http://gitea.yakenator.io
- **사용자**: yakenator
- **비밀번호**: asdfg23we
### 새 리포지토리 생성 (API)
```bash
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}'
```
### 새 프로젝트 초기화 및 푸시
```bash
# 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"에 추가하면 프로젝트 컨텍스트를 공유할 수 있습니다.