저는 HolySheep AI에서 3년간 AI 게이트웨이 인프라를 설계해 온 시니어 엔지니어입니다. 오늘은 Dify를 프로덕션 환경에 배포하고 REST 엔드포인트를 구성하는 방법을 깊이 있게 다룹니다. 특히 HolySheep AI 게이트웨이를 활용한 비용 최적화와 동시성 제어에 집중하겠습니다.

Dify와 REST API 아키텍처 이해

Dify는 오픈소스 LLM 앱 개발 플랫폼으로, 자체 호스팅이 가능하면서도 RESTful API를 통해 외부 시스템과 연동됩니다. Dify의 API는 세 가지 주요 유형으로 구분됩니다:

프로덕션 환경에서는 Dify 서버가 직접 외부 트래픽을 받는 것보다, 게이트웨이를 통해 라우팅하는 것이 안전합니다. 여기서 HolySheep AI의 역할이 중요해집니다.

HolySheep AI 게이트웨이 통합

HolySheep AI는 40개 이상의 AI 모델을 단일 엔드포인트로 통합합니다. Dify의 자체 모델 연동 대신 HolySheep AI를 프록시로 사용하면:

먼저 HolySheep AI에 지금 가입하여 API 키를 발급받습니다.

프로덕션-ready REST Endpoint 구성

1. Dify 서버 기본 설정

# docker-compose.yml for Dify Server
version: '3.8'

services:
  dify-api:
    image: langgenius/dify-api:0.14.0
    container_name: dify-api
    restart: unless-stopped
    environment:
      - SECRET_KEY=${SECRET_KEY}
      - CONSOLE_WEB_URL=https://your-dify-console.com
      - CONSOLE_API_URL=https://your-dify-console.com
      - SERVICE_API_URL=https://your-dify-api.com
      - DB_USERNAME=postgres
      - DB_PASSWORD=${DB_PASSWORD}
      - DB_HOST=postgres
      - DB_PORT=5432
      - DB_DATABASE=dify
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - REDIS_PASSWORD=${REDIS_PASSWORD}
      - MODEL_DISK_CACHE_DIR=/app/api/model-cache
      - WORKDIR=/app/api
    ports:
      - "5001:5001"
    volumes:
      - ./volumes/dify_api:/app/api
      - ./nginx/ssl:/etc/nginx/ssl:ro
    depends_on:
      - postgres
      - redis
    networks:
      - dify-network
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5001/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  nginx:
    image: nginx:1.25-alpine
    container_name: dify-nginx
    restart: unless-stopped
    ports:
      - "443:443"
      - "80:80"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
    depends_on:
      - dify-api
    networks:
      - dify-network

networks:
  dify-network:
    driver: bridge

2. HolySheep AI 게이트웨이 연동 Python 클라이언트

import asyncio
import aiohttp
import hashlib
import time
from typing import Optional, Dict, Any, AsyncIterator
from dataclasses import dataclass
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

@dataclass
class DifyConfig:
    """Dify REST API 설정"""
    base_url: str = "https://your-dify-api.com"
    api_key: str = "your-dify-api-key"
    app_id: str = "your-app-uuid"
    request_timeout: int = 120
    max_retries: int = 3

@dataclass  
class HolySheepConfig:
    """HolySheep AI 게이트웨이 설정"""
    base_url: str = "https://api.holysheep.ai/v1"
    api_key: str = "YOUR_HOLYSHEEP_API_KEY"
    model: str = "gpt-4.1"
    temperature: float = 0.7
    max_tokens: int = 2048

class DifyHolySheepGateway:
    """
    Dify와 HolySheep AI를 연동하는 게이트웨이 클라이언트
    
    프로덕션 환경에서의 주요 기능:
    - Streaming/Non-streaming 응답 지원
    - 자동 재시도 및 지수 백오프
    - 동시성 제어 (Semaphore 기반)
    - 토큰 사용량 추적
    - 비용 최적화 라우팅
    """
    
    def __init__(
        self,
        dify_config: DifyConfig,
        holy_config: HolySheepConfig,
        max_concurrent: int = 50
    ):
        self.dify = dify_config
        self.holy = holy_config
        self._semaphore = asyncio.Semaphore(max_concurrent)
        self._session: Optional[aiohttp.ClientSession] = None
        
        # 비용 추적
        self.total_tokens = 0
        self.total_cost = 0.0
        
    async def __aenter__(self):
        timeout = aiohttp.ClientTimeout(
            total=self.dify.request_timeout,
            connect=30,
            sock_read=60
        )
        self._session = aiohttp.ClientSession(timeout=timeout)
        return self
        
    async def __aexit__(self, *args):
        if self._session:
            await self._session.close()
    
    def _get_headers(self) -> Dict[str, str]:
        """Dify API 요청 헤더 생성"""
        timestamp = str(int(time.time()))
        signature = hashlib.sha256(
            f"{self.dify.api_key}{timestamp}".encode()
        ).hexdigest()
        
        return {
            "Authorization": f"Bearer {self.dify.api_key}",
            "Content-Type": "application/json",
            "X-Dify-Timestamp": timestamp,
            "X-Dify-Signature": signature,
            "X-App-Id": self.dify.app_id
        }
    
    def _get_holy_headers(self) -> Dict[str, str]:
        """HolySheep AI API 요청 헤더"""
        return {
            "Authorization": f"Bearer {self.holy.api_key}",
            "Content-Type": "application/json"
        }
    
    async def _retry_request(
        self,
        method: str,
        url: str,
        **kwargs
    ) -> aiohttp.ClientResponse:
        """지수 백오프를 사용한 자동 재시도"""
        last_exception = None
        
        for attempt in range(self.holy.max_retries if hasattr(self.holy, 'max_retries') else 3):
            try:
                async with self._session.request(
                    method, url, **kwargs
                ) as response:
                    if response.status == 200:
                        return response
                    elif response.status == 429:
                        # Rate limit - 백오프 후 재시도
                        wait_time = (2 ** attempt) * 1.5
                        logger.warning(f"Rate limited. Waiting {wait_time}s before retry...")
                        await asyncio.sleep(wait_time)
                        continue
                    else:
                        response.raise_for_status()
                        return response
                        
            except aiohttp.ClientError as e:
                last_exception = e
                wait_time = (2 ** attempt) * 2
                logger.warning(f"Request failed: {e}. Retrying in {wait_time}s...")
                await asyncio.sleep(wait_time)
                
        raise last_exception or Exception("Max retries exceeded")
    
    async def chat_completion(
        self,
        messages: list,
        stream: bool = False,
        session_id: Optional[str] = None,
        extra_params: Optional[Dict[str, Any]] = None
    ) -> AsyncIterator[str] | Dict[str, Any]:
        """
        HolySheep AI를 통해 Dify 앱과 연동된 채팅 완료 생성
        
        Args:
            messages: [{"role": "user", "content": "..."}] 형식의 메시지 리스트
            stream: True면 SSE 스트리밍 응답
            session_id: 대화 세션 유지용 ID
            extra_params: 모델별 추가 파라미터
            
        Returns:
            stream=True: 비동기 문자열 이터레이터
            stream=False: 완성된 응답 딕셔너리
        """
        async with self._semaphore:
            # HolySheep AI에 먼저 요청하여 비용 최적화
            holy_request = {
                "model": self.holy.model,
                "messages": messages,
                "temperature": self.holy.temperature,
                "max_tokens": self.holy.max_tokens,
                "stream": stream
            }
            
            if extra_params:
                holy_request.update(extra_params)
            
            url = f"{self.holy.base_url}/chat/completions"
            headers = self._get_holy_headers()
            
            logger.info(f"Requesting {self.holy.model} via HolySheep AI")
            start_time = time.time()
            
            async with self._session.post(
                url,
                json=holy_request,
                headers=headers
            ) as response:
                if stream:
                    return self._handle_stream_response(response, start_time)
                else:
                    result = await response.json()
                    self._track_cost(result, start_time)
                    return result
    
    async def _handle_stream_response(
        self,
        response: aiohttp.ClientResponse,
        start_time: float
    ) -> AsyncIterator[str]:
        """SSE 스트리밍 응답 처리"""
        accumulated_content = []
        
        async for line in response.content:
            line = line.decode('utf-8').strip()
            
            if not line or not line.startswith('data: '):
                continue
                
            data = line[6:]  # "data: " 접두사 제거
            
            if data == '[DONE]':
                break
                
            try:
                chunk = json.loads(data)
                if 'choices' in chunk:
                    delta = chunk['choices'][0].get('delta', {})
                    content = delta.get('content', '')
                    if content:
                        accumulated_content.append(content)
                        yield content
                        
            except json.JSONDecodeError:
                continue
        
        # 토큰 사용량 계산
        elapsed = time.time() - start_time
        logger.info(f"Stream completed in {elapsed:.2f}s, "
                   f"chars: {len(''.join(accumulated_content))}")
    
    def _track_cost(self, result: Dict[str, Any], start_time: float):
        """토큰 사용량 및 비용 추적"""
        if 'usage' in result:
            usage = result['usage']
            tokens = usage.get('total_tokens', 0)
            prompt_tokens = usage.get('prompt_tokens', 0)
            completion_tokens = usage.get('completion_tokens', 0)
            
            # HolySheep AI 가격표 기반 비용 계산
            price_map = {
                "gpt-4.1": 8.0,       # $8/MTok
                "claude-sonnet-4": 15.0,  # $15/MTok
                "gemini-2.5-flash": 2.5,  # $2.50/MTok
                "deepseek-v3.2": 0.42,   # $0.42/MTok
            }
            
            price_per_mtok = price_map.get(self.holy.model, 8.0)
            cost = (tokens / 1_000_000) * price_per_mtok
            
            self.total_tokens += tokens
            self.total_cost += cost
            
            elapsed = time.time() - start_time
            logger.info(
                f"Tokens: {tokens:,} | "
                f"Cost: ${cost:.4f} | "
                f"Latency: {elapsed:.2f}s"
            )


async def main():
    """프로덕션 사용 예시"""
    
    dify_config = DifyConfig(
        base_url="https://api.your-dify-instance.com",
        api_key="app-xxxxxxxxxxxx",
        app_id="app-uuid-here",
        request_timeout=120
    )
    
    holy_config = HolySheepConfig(
        api_key="YOUR_HOLYSHEEP_API_KEY",
        model="gpt-4.1",
        temperature=0.7,
        max_tokens=2048
    )
    
    async with DifyHolySheepGateway(
        dify_config=dify_config,
        holy_config=holy_config,
        max_concurrent=50
    ) as gateway:
        
        # 스트리밍 요청 예시
        messages = [
            {"role": "system", "content": "당신은 도움이 되는 AI 어시스턴트입니다."},
            {"role": "user", "content": "Dify와 HolySheep AI 통합 설정 방법을 알려주세요."}
        ]
        
        print("Streaming Response:")
        async for chunk in await gateway.chat_completion(
            messages=messages,
            stream=True
        ):
            print(chunk, end="", flush=True)
        print("\n")
        
        # 일반 요청 예시
        result = await gateway.chat_completion(
            messages=messages,
            stream=False
        )
        print(f"Full Response: {result['choices'][0]['message']['content']}")
        print(f"Total Cost So Far: ${gateway.total_cost:.4f}")

if __name__ == "__main__":
    asyncio.run(main())

동시성 제어 및 성능 튜닝

프로덕션 환경에서 가장 중요한 것은 동시성 제어입니다. HolySheep AI의 Rate Limit은 모델마다 다르므로:

Semaphore를 사용한 동시성 제한 구현:

import asyncio
from collections import defaultdict
from typing import Dict
import time

class AdaptiveRateLimiter:
    """
    HolySheep AI 모델별 Rate Limit에 적응하는 동적 Rate Limiter
    
    특징:
    - 모델별 독립적인 Rate Limit 추적
    - 슬라이딩 윈도우 기반 토큰 카운팅
    - 자동 백오프 및 요청 스케줄링
    """
    
    def __init__(self):
        # 모델별 RPM (Requests Per Minute) 제한
        self.model_limits: Dict[str, Dict] = {
            "gpt-4.1": {"rpm": 500, "tpm": 1_000_000, "window": 60},
            "gpt-4o": {"rpm": 500, "tpm": 1_000_000, "window": 60},
            "claude-sonnet-4": {"rpm": 1000, "tpm": float('inf'), "window": 60},
            "gemini-2.5-flash": {"rpm": 2000, "tpm": float('inf'), "window": 60},
            "deepseek-v3.2": {"rpm": 3000, "tpm": 1_500_000, "window": 60},
        }
        
        # 슬라이딩 윈도우 추적
        self.request_timestamps: Dict[str, list] = defaultdict(list)
        self.token_usage: Dict[str, list] = defaultdict(list)
        
        # 글로벌 세마포어
        self._global_semaphore = asyncio.Semaphore(100)
        self._model_semaphores: Dict[str, asyncio.Semaphore] = {}
        
        for model in self.model_limits:
            rpm = self.model_limits[model]["rpm"]
            self._model_semaphores[model] = asyncio.Semaphore(rpm)
    
    def _clean_old_entries(self, timestamps: list, window: int) -> list:
        """윈도우 기간이 지난 엔트리 제거"""
        current_time = time.time()
        cutoff = current_time - window
        return [ts for ts in timestamps if ts > cutoff]
    
    async def acquire(self, model: str, estimated_tokens: int = 1000):
        """
        Rate Limit 내에서 요청 실행 허가 획득
        
        Args:
            model: 모델명
            estimated_tokens: 예상 토큰 수 (tpm 제한 확인용)
        """
        await self._global_semaphore.acquire()
        
        try:
            limit = self.model_limits.get(model)
            if not limit:
                limit = {"rpm": 100, "tpm": float('inf'), "window": 60}
            
            current_time = time.time()
            
            # RPM 체크
            self.request_timestamps[model] = self._clean_old_entries(
                self.request_timestamps[model], limit["window"]
            )
            
            rpm_count = len(self.request_timestamps[model])
            if rpm_count >= limit["rpm"]:
                oldest = self.request_timestamps[model][0]
                wait_time = oldest + limit["window"] - current_time
                if wait_time > 0:
                    await asyncio.sleep(wait_time)
                    self.request_timestamps[model] = self._clean_old_entries(
                        self.request_timestamps[model], limit["window"]
                    )
            
            # TPM 체크
            if limit["tpm"] != float('inf'):
                self.token_usage[model] = self._clean_old_entries(
                    self.token_usage[model], limit["window"]
                )
                
                current_tpm = sum(self.token_usage[model])
                if current_tpm + estimated_tokens > limit["tpm"]:
                    oldest_token_time = self.token_usage[model][0] if self.token_usage[model] else current_time
                    wait_time = oldest_token_time + limit["window"] - current_time
                    if wait_time > 0:
                        await asyncio.sleep(wait_time)
            
            # 성공적으로 허가 획득
            self.request_timestamps[model].append(current_time)
            self.token_usage[model].append(estimated_tokens)
            
        finally:
            self._global_semaphore.release()
    
    async def batch_process(
        self,
        items: list,
        process_func,
        model: str = "gpt-4.1",
        batch_size: int = 10
    ):
        """
        배치 요청 처리 (병렬 처리 + Rate Limit 준수)
        
        Args:
            items: 처리할 아이템 리스트
            process_func: 각 아이템 처리 함수 (async)
            model: 사용할 모델
            batch_size: 한 번에 처리할 배치 크기
        """
        results = []
        
        for i in range(0, len(items), batch_size):
            batch = items[i:i + batch_size]
            
            # 배치 내 병렬 처리
            tasks = []
            for item in batch:
                task = asyncio.create_task(
                    self._process_with_limit(item, process_func, model)
                )
                tasks.append(task)
            
            batch_results = await asyncio.gather(*tasks, return_exceptions=True)
            results.extend(batch_results)
            
            # 배치 간 딜레이 (Rate Limit 안정화)
            if i + batch_size < len(items):
                await asyncio.sleep(1.0)
        
        return results
    
    async def _process_with_limit(self, item, process_func, model):
        """Rate Limit을 지키며 단일 아이템 처리"""
        async with self._model_semaphores[model]:
            await self.acquire(model, estimated_tokens=1500)
            return await process_func(item)


사용 예시

async def example_usage(): limiter = AdaptiveRateLimiter() async def process_item(item: dict): # 실제 API 호출 시뮬레이션 await asyncio.sleep(0.1) return f"Processed: {item['id']}" items = [{"id": i, "data": f"item_{i}"} for i in range(100)] start = time.time() results = await limiter.batch_process( items=items, process_func=process_item, model="deepseek-v3.2", # 가장 높은 Rate Limit batch_size=50 ) elapsed = time.time() - start print(f"Processed {len(results)} items in {elapsed:.2f}s") print(f"Throughput: {len(results)/elapsed:.2f} items/s") if __name__ == "__main__": asyncio.run(example_usage())

비용 최적화 전략

HolySheep AI를 사용하면 모델별 가격 차이가 큽니다:

비용 최적화를 위한 라우팅 전략:

import asyncio
from enum import Enum
from dataclasses import dataclass
from typing import Optional, Callable
import hashlib

class TaskComplexity(Enum):
    """작업 복잡도 분류"""
    SIMPLE = "simple"      # 단순 질문, 요약
    MODERATE = "moderate"  # 분석, 변환
    COMPLEX = "complex"    # 복잡한推理, 코드 생성

@dataclass
class CostOptimizationConfig:
    """비용 최적화 설정"""
    # 복잡도별 모델 매핑
    model_mapping: dict = None
    
    # 자동 복잡도 감지 사용 여부
    auto_detect: bool = True
    
    # 비용 절감 목표 (%)
    target_savings: float = 50.0
    
    def __post_init__(self):
        if self.model_mapping is None:
            self.model_mapping = {
                TaskComplexity.SIMPLE: {
                    "model": "deepseek-v3.2",
                    "max_tokens": 512,
                    "price": 0.42
                },
                TaskComplexity.MODERATE: {
                    "model": "gemini-2.5-flash",
                    "max_tokens": 2048,
                    "price": 2.50
                },
                TaskComplexity.COMPLEX: {
                    "model": "gpt-4.1",
                    "max_tokens": 4096,
                    "price": 8.00
                }
            }

class IntelligentCostRouter:
    """
    작업 복잡도에 따라 최적의 모델로 자동 라우팅
    
    핵심 기능:
    - 프롬프트 기반 자동 복잡도 감지
    - 비용 대 성능trade-off 최적화
    - 응답 품질 모니터링 및 모델 업그레이드
    """
    
    # 단순 작업 지시 키워드
    SIMPLE_KEYWORDS = [
        "what is", "who is", "when did", "define",
        "translate", "summarize", "list", "count",
        "simple", "brief", "quick"
    ]
    
    # 복잡 작업 지시 키워드
    COMPLEX_KEYWORDS = [
        "analyze deeply", "compare and contrast",
        "design", "architect", "complex", "detailed",
        "reasoning", "prove", "evaluate critically"
    ]
    
    def __init__(self, config: Optional[CostOptimizationConfig] = None):
        self.config = config or CostOptimizationConfig()
        self.total_requests = 0
        self.cost_breakdown = {
            "simple": {"count": 0, "cost": 0.0},
            "moderate": {"count": 0, "cost": 0.0},
            "complex": {"count": 0, "cost": 0.0}
        }
    
    def detect_complexity(self, prompt: str, messages: list = None) -> TaskComplexity:
        """프롬프트 분석을 통한 복잡도 감지"""
        combined_text = prompt.lower()
        
        if messages:
            combined_text += " " + " ".join(
                m.get("content", "").lower() for m in messages
            )
        
        # 복잡도 점수 계산
        complexity_score = 0
        
        for keyword in self.COMPLEX_KEYWORDS:
            if keyword in combined_text:
                complexity_score += 2
        
        for keyword in self.SIMPLE_KEYWORDS:
            if keyword in combined_text:
                complexity_score -= 1
        
        # 토큰 수 기반 추정 (긴 입력 = 복잡한 작업 가능성)
        estimated_tokens = len(combined_text.split()) * 1.3
        if estimated_tokens > 500:
            complexity_score += 1
        if estimated_tokens > 2000:
            complexity_score += 2
        
        # 복잡도 분류
        if complexity_score <= -1:
            return TaskComplexity.SIMPLE
        elif complexity_score <= 2:
            return TaskComplexity.MODERATE
        else:
            return TaskComplexity.COMPLEX
    
    def get_optimal_model(
        self,
        prompt: str,
        messages: list = None,
        forced_complexity: Optional[TaskComplexity] = None
    ) -> tuple[str, dict]:
        """
        비용 효율적인 모델 선택
        
        Returns:
            (model_name, model_params)
        """
        complexity = (
            forced_complexity or 
            self.detect_complexity(prompt, messages)
        )
        
        model_info = self.config.model_mapping[complexity]
        
        self.total_requests += 1
        
        return model_info["model"], {
            "max_tokens": model_info["max_tokens"],
            "temperature": 0.7 if complexity != TaskComplexity.SIMPLE else 0.3,
            "complexity": complexity.value
        }
    
    def calculate_potential_savings(
        self,
        total_requests: int,
        avg_complexity_distribution: dict
    ) -> dict:
        """
        최적화 가능한 비용 절감액 계산
        
        Args:
            total_requests: 총 요청 수
            avg_complexity_distribution: {"simple": 0.5, "moderate": 0.3, "complex": 0.2}
        """
        baseline_model = "gpt-4.1"
        baseline_cost_per_1k = 8.00
        
        # 현재 비용 (전부 GPT-4.1 사용 가정)
        baseline_total = (
            total_requests * 1000 * baseline_cost_per_1k / 1_000_000
        )
        
        # 최적화 후 비용
        optimized_total = 0.0
        for complexity, ratio in avg_complexity_distribution.items():
            model_info = self.config.model_mapping[TaskComplexity[complexity.upper()]]
            requests_count = total_requests * ratio
            cost = requests_count * 1000 * model_info["price"] / 1_000_000
            optimized_total += cost
            
            self.cost_breakdown[complexity]["count"] = int(requests_count)
            self.cost_breakdown[complexity]["cost"] = cost
        
        savings = baseline_total - optimized_total
        savings_percent = (savings / baseline_total) * 100 if baseline_total > 0 else 0
        
        return {
            "baseline_cost": baseline_total,
            "optimized_cost": optimized_total,
            "savings": savings,
            "savings_percent": savings_percent,
            "breakdown": self.cost_breakdown
        }
    
    async def execute_with_routing(
        self,
        gateway: 'DifyHolySheepGateway',
        prompt: str,
        messages: list = None,
        forced_model: Optional[str] = None
    ):
        """
        최적화된 모델로 요청 실행
        """
        if forced_model:
            model = forced_model
            params = {"temperature": 0.7}
        else:
            model, params = self.get_optimal_model(prompt, messages)
        
        # HolySheep AI를 통한 요청
        return await gateway.chat_completion(
            messages=messages or [{"role": "user", "content": prompt}],
            stream=False,
            extra_params=params
        )


사용 예시

async def cost_optimization_example(): router = IntelligentCostRouter() prompts = [ ("What is Python?", TaskComplexity.SIMPLE), ("Analyze the pros and cons of microservices architecture.", TaskComplexity.MODERATE), ("Design a distributed system that handles 1M requests per second.", TaskComplexity.COMPLEX), ("Summarize this article: [content...]", TaskComplexity.SIMPLE), ("Compare React vs Vue for enterprise applications.", TaskComplexity.MODERATE), ] print("=== Prompt Complexity Detection ===\n") for prompt, expected in prompts: detected = router.detect_complexity(prompt) model, params = router.get_optimal_model(prompt) status = "✓" if detected == expected else "✗" print(f"{status} Prompt: {prompt[:50]}...") print(f" Expected: {expected.value}, Detected: {detected.value}") print(f" Routed to: {model}\n") # 비용 절감 시뮬레이션 savings = router.calculate_potential_savings( total_requests=10_000, avg_complexity_distribution={ "simple": 0.5, "moderate": 0.35, "complex": 0.15 } ) print("=== Cost Optimization Projection (10K requests) ===") print(f"Baseline (all GPT-4.1): ${savings['baseline_cost']:.2f}") print(f"Optimized: ${savings['optimized_cost']:.2f}") print(f"Savings: ${savings['savings']:.2f} ({savings['savings_percent']:.1f}%)") if __name__ == "__main__": asyncio.run(cost_optimization_example())

Nginx 리버스 프록시 설정

# /etc/nginx/nginx.conf

worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    
    # 로깅
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for" '
                    'rt=$request_time uct="$upstream_connect_time" '
                    'uht="$upstream_header_time" urt="$upstream_response_time"';
    
    access_log /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log warn;
    
    # 성능 최적화
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 1000;
    
    # 버퍼 설정
    client_body_buffer_size 16k;
    client_max_body_size 100m;
    proxy_buffer_size 128k;
    proxy_buffers 4 256k;
    proxy_busy_buffers_size 256k;
    
    # Gzip 압축
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript 
               text/xml application/xml text/csv;
    
    # Rate Limiting Zones
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
    
    upstream dify_backend {
        least_conn;
        server dify-api:5001 weight=5;
        server dify-api-2:5001 weight=5;
        keepalive 32;
    }
    
    server {
        listen 443 ssl http2;
        server_name your-dify-api.com;
        
        # SSL 설정
        ssl_certificate /etc/nginx/ssl/fullchain.pem;
        ssl_certificate_key /etc/nginx/ssl/privkey.pem;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
        ssl_prefer_server_ciphers off;
        ssl_session_cache shared:SSL:50m;
        ssl_session_timeout 1d;
        
        # 헬스체크 경로 (_rate_limit 미적용)
        location = /health {
            access_log off;
            return 200 "healthy\n";
            add_header Content-Type text/plain;
        }
        
        # Dify API 프록시
        location /v1 {
            # 요청 제한
            limit_req zone=api_limit burst=200 nodelay;
            limit_conn conn_limit 50;
            
            # 타임아웃 설정
            proxy_http_version 1.1;
            proxy_connect_timeout 60s;
            proxy_send_timeout 300s;
            proxy_read_timeout 300s;
            
            # 헤더 전달
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Connection "";
            
            # SSE(Streaming) 지원
            proxy_buffering off;
            proxy_cache off;
            chunked_transfer_encoding on;
            
            proxy_pass http://dify_backend/v1;
        }
        
        # WebSocket 지원 (필요시)
        location /ws {
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_connect_timeout 7s;
            proxy_send_timeout 24h;
            proxy_read_timeout 24h;
            
            proxy_pass http://dify_backend;
        }
    }
    
    # HTTP → HTTPS 리다이렉트
    server {
        listen 80;
        server_name your-dify-api.com;
        return 301 https://$server_name$request_uri;
    }
}

모니터링 및 로그 설정

프로덕션 환경에서는 요청 추적이 필수입니다:

import structlog
from prometheus_client import Counter, Histogram, Gauge
import time
from functools import wraps
from typing import Callable

Prometheus 메트릭

request_counter = Counter( 'dify_requests_total', 'Total Dify API requests', ['model', 'status', 'complexity'] ) request_duration = Histogram( 'dify_request_duration_seconds', 'Request duration in seconds', ['model', 'endpoint'], buckets=[0.1, 0.5, 1.0, 2.0, 5.0, 10.0, 30.0, 60.0] ) token_gauge = Gauge( 'dify_tokens_used', 'Tokens used', ['model', 'type'] # type: prompt/completion/total ) cost_gauge = Gauge( 'dify_cost_usd', 'Total cost in USD', ['model'] )

structlog 설정

structlog.configure( processors=[ structlog.contextvars.merge_contextvars, structlog.process