# 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 ``` --- ## 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>({ 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"에 추가하면 프로젝트 컨텍스트를 공유할 수 있습니다.