AI API를 실무에 도입하면 예상치 못한 오류들이 개발 과정을 방해합니다. 인증 실패부터 속도 제한, 서버 장애까지 — 이 튜토리얼에서는 HolySheep AI를Gateway로 활용하여 이러한 문제들을 효과적으로 해결하는 방법을 설명합니다.笔者는 3년간 다양한 AI API를 실무에 적용하며 축적한 경험을 바탕으로 실제 발생했던 오류 상황과 구체적인 해결 코드를 공유합니다.

OpenAI API 제공자 비교 분석

AI API를 사용하려면 여러 제공자 중에서 선택해야 합니다. 각 서비스의 장단점을 정확히 이해해야 비용과 안정성 측면에서 최적의 선택을 할 수 있습니다.

비교 항목 HolySheep AI 공식 OpenAI API 타 Relay 서비스
결제 방식 로컬 결제 지원 (국내 계좌) 해외 신용카드 필수 해외 신용카드 또는 복잡한 과정
API 엔드포인트 단일 키로 다중 모델 통합 각厂商별 개별 키 필요 서비스별 상이
GPT-4.1 비용 $8.00/MTok $8.00/MTok $9~12/MTok
Claude Sonnet 4.5 $15.00/MTok $15.00/MTok $16~20/MTok
Gemini 2.5 Flash $2.50/MTok $2.50/MTok $3~5/MTok
DeepSeek V3.2 $0.42/MTok 공식 지원 없음 불안정하거나 지원 중단
평균 응답 속도 150~300ms 100~250ms 300~800ms
무료 크레딧 가입 시 즉시 제공 $5 초기 크레딧 제한적이거나 없음
速率 제한 유연한 할당량 관리 엄격한 RPM/TPM 제한 서비스마다 상이
고객 지원 한국어 실시간 지원 이메일 지원만 제한적 지원

이런 팀에 적합 / 비적합

HolySheep AI가 완벽히 적합한 팀

다른 옵션을 고려해야 하는 경우

자주 발생하는 오류와 해결책

실무에서 가장 자주 마주치는 7가지 오류 카테고리와 구체적인 해결 코드를 제공합니다. 각 오류는 실제 프로덕션 환경에서 발생했던 상황을 바탕으로 작성되었습니다.

1. 인증 오류 (Authentication Error)

증상: API 호출 시 401 Unauthorized 또는 403 Forbidden 응답

원인 분석: API 키 누락, 잘못된 형식, 만료된 키, 또는 권한 부족이主要原因입니다. 특히 Relay 서비스를 사용할 경우 엔드포인트 설정 오류도 흔한 원인입니다.

# 잘못된 예: 공식 API 엔드포인트 사용 (불필요한 지연 및 장애 위험)
import openai
openai.api_key = "sk-..."
openai.api_base = "https://api.openai.com/v1"  # 이 주소 사용 금지

올바른 예: HolySheep AI Gateway 사용

import openai openai.api_key = "YOUR_HOLYSHEEP_API_KEY" openai.api_base = "https://api.holysheep.ai/v1"

모델 지정 (원하는 모델로 자유롭게 변경 가능)

response = openai.ChatCompletion.create( model="gpt-4.1", messages=[{"role": "user", "content": "안녕하세요"}] ) print(response.choices[0].message.content)
# 환경 변수 설정 방식 (더 안전한 접근)
import os
import openai

환경 변수에서 API 키 로드

openai.api_key = os.environ.get("HOLYSHEEP_API_KEY") openai.api_base = "https://api.holysheep.ai/v1"

키 유효성 검증 함수

def validate_api_key(): try: models = openai.Model.list() print("API 키 인증 성공!") print(f"사용 가능한 모델 수: {len(models.data)}") return True except openai.error.AuthenticationError as e: print(f"인증 실패: {e}") return False except Exception as e: print(f"예상치 못한 오류: {e}") return False validate_api_key()

2. 속도 제한 오류 (Rate Limit Error)

증상: 429 Too Many Requests 응답, "Rate limit exceeded" 메시지

원인 분석: 요청 빈도가 분당 허용량을 초과하거나, 분당 토큰 수(TPM)가 할당량을넘어설 때 발생합니다. 일괄 처리 시 특히 흔하게 나타납니다.

import openai
import time
import asyncio
from collections import defaultdict
from datetime import datetime, timedelta

openai.api_key = "YOUR_HOLYSHEEP_API_KEY"
openai.api_base = "https://api.holysheep.ai/v1"

지数 백오프 기반 재시도 로직

def exponential_backoff_with_jitter(max_retries=5): """기하 백오프와 무작위 지연시간을 조합한 고급 재시도 로직""" def decorator(func): def wrapper(*args, **kwargs): base_delay = 1 max_delay = 60 for attempt in range(max_retries): try: return func(*args, **kwargs) except openai.error.RateLimitError as e: if attempt == max_retries - 1: raise e # 지수적 증가 + 무작위 지터 delay = min(base_delay * (2 ** attempt), max_delay) jitter = delay * 0.2 * (hash(str(time.time())) % 10) / 10 wait_time = delay + jitter print(f"속도 제한 도달. {wait_time:.1f}초 후 재시도... ({attempt + 1}/{max_retries})") time.sleep(wait_time) return wrapper return decorator @exponential_backoff_with_jitter(max_retries=5) def call_api_with_retry(prompt, model="gpt-4.1"): response = openai.ChatCompletion.create( model=model, messages=[{"role": "user", "content": prompt}], temperature=0.7, max_tokens=500 ) return response

사용 예시

prompts = ["질문 1", "질문 2", "질문 3"] for i, prompt in enumerate(prompts): print(f"[{i+1}/{len(prompts)}] 처리 중...") result = call_api_with_retry(prompt) print(f"응답: {result.choices[0].message.content[:50]}...") time.sleep(0.5) # 배치 처리 간 최소 간격
import asyncio
import aiohttp
from aiohttp import ClientTimeout

동시 요청 관리자

class RateLimitedAsyncClient: def __init__(self, api_key, requests_per_minute=60): self.api_key = api_key self.base_url = "https://api.holysheep.ai/v1" self.rpm_limit = requests_per_minute self.request_times = [] self.semaphore = asyncio.Semaphore(5) # 최대 동시 요청 5개 async def wait_for_rate_limit(self): """분당 요청 수 제한 준수""" now = datetime.now() # 1분 이내의 요청만 필터링 self.request_times = [t for t in self.request_times if now - t < timedelta(minutes=1)] if len(self.request_times) >= self.rpm_limit: oldest = min(self.request_times) wait_seconds = 60 - (now - oldest).total_seconds() if wait_seconds > 0: print(f"속도 제한 도달. {wait_seconds:.1f}초 대기...") await asyncio.sleep(wait_seconds) self.request_times.append(datetime.now()) async def chat_completion(self, prompt, model="gpt-4.1"): async with self.semaphore: await self.wait_for_rate_limit() headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json" } payload = { "model": model, "messages": [{"role": "user", "content": prompt}] } timeout = ClientTimeout(total=30) async with aiohttp.ClientSession(timeout=timeout) as session: async with session.post( f"{self.base_url}/chat/completions", headers=headers, json=payload ) as response: if response.status == 429: raise aiohttp.ClientResponseError( response.request_info, response.history, status=429, message="Rate limit exceeded" ) return await response.json()

사용 예시

async def main(): client = RateLimitedAsyncClient("YOUR_HOLYSHEEP_API_KEY", requests_per_minute=60) prompts = [ "한국의 수도는 어디인가요?", "파이는 approximately 얼마인가요?", "태양계에서 가장 큰 행성은 무엇인가요?" ] tasks = [client.chat_completion(p) for p in prompts] results = await asyncio.gather(*tasks, return_exceptions=True) for i, result in enumerate(results): if isinstance(result, Exception): print(f"프로프트 {i+1} 오류: {result}") else: content = result.get("choices", [{}])[0].get("message", {}).get("content", "") print(f"프로프트 {i+1} 응답: {content}") asyncio.run(main())

3. 컨텍스트 길이 초과 오류 (Context Length Exceeded)

증상: 400 Bad Request, "maximum context length exceeded" 또는 "token limit exceeded"

원인 분석: 입력 텍스트와 예상 출력을 합친 토큰 수가 모델의 최대 컨텍스트 창을초과할 때 발생합니다. 긴 문서 처리나 대화 히스토리累积 시 자주 나타납니다.

import tiktoken  # 토큰 카운팅 라이브러리

모델별 컨텍스트 창 크기 (토큰 단위)

MODEL_MAX_TOKENS = { "gpt-4.1": 128000, "gpt-4-turbo": 128000, "gpt-3.5-turbo": 16385, "claude-3-5-sonnet-20241022": 200000, "gemini-2.5-flash": 1000000 } def count_tokens(text, model="gpt-4.1"): """텍스트의 토큰 수를 계산합니다""" encoding = tiktoken.encoding_for_model("gpt-4") return len(encoding.encode(text)) def truncate_to_fit_system_prompt(messages, model="gpt-4.1", reserved_output_tokens=500): """ 컨텍스트 창에 맞게 메시지를 자릅니다 시스템 프롬프트를 제외한 나머지 메시지의 길이를 조정합니다 """ max_tokens = MODEL_MAX_TOKENS.get(model, 128000) available_tokens = max_tokens - reserved_output_tokens # 역순으로遍历하여 오래된 메시지부터 제거 truncated_messages = [] current_tokens = 0 for message in reversed(messages): message_tokens = count_tokens(str(message["content"])) + 4 # 메시지 오버헤드 if current_tokens + message_tokens <= available_tokens: truncated_messages.insert(0, message) current_tokens += message_tokens else: # 다음 메시지가 시스템 메시지이면 중단 if message["role"] == "system": break print(f"메시지 제거됨: {message.get('role', 'unknown')} - 약 {message_tokens} 토큰") return truncated_messages def smart_message_preparation(conversation_history, new_prompt, model="gpt-4.1"): """지능형 메시지 준비: 컨텍스트 초과를 방지하면서 핵심 대화 유지""" system_message = {"role": "system", "content": "당신은 도움이 되는 AI 어시스턴트입니다."} # 메시지 구성 messages = [system_message] messages.extend(conversation_history) messages.append({"role": "user", "content": new_prompt}) # 토큰 계산 total_tokens = sum(count_tokens(str(m.get("content", ""))) for m in messages) + len(messages) * 4 print(f"총 토큰 수: {total_tokens:,} / {MODEL_MAX_TOKENS[model]:,} ({total_tokens/MODEL_MAX_TOKENS[model]*100:.1f}%)") if total_tokens > MODEL_MAX_TOKENS[model] - 500: print("컨텍스트 초과 감지. 오래된 메시지를 자동으로 제거합니다...") conversation_only = messages[1:-1] # 시스템과 현재 입력 제외 truncated = truncate_to_fit_system_prompt(conversation_only, model) return [system_message] + truncated + [{"role": "user", "content": new_prompt}] return messages

사용 예시

import openai openai.api_key = "YOUR_HOLYSHEEP_API_KEY" openai.api_base = "https://api.holysheep.ai/v1"

긴 대화 시뮬레이션

long_conversation = [ {"role": "user", "content": "프로그래밍 언어에 대해 설명해주세요." * 100}, {"role": "assistant", "content": "프로그래밍 언어는 컴퓨터와 소통하기 위한 형식적 언어입니다..." * 100}, {"role": "user", "content": "파이썬의 특징은 무엇인가요?" * 50} ] final_messages = smart_message_preparation(long_conversation, "자바스크립트의 특징은?", model="gpt-4.1") response = openai.ChatCompletion.create( model="gpt-4.1", messages=final_messages, max_tokens=500 ) print(f"응답 길이: {len(response.choices[0].message.content)}자")

4. 타임아웃 오류 (Timeout Error)

증상: 요청이 응답 없이 무한 대기하거나 504 Gateway Timeout 응답

원인 분석: 긴 컨텍스트 처리, 네트워크 지연, 또는 서버 과부하가主要原因입니다. 특히 복잡한 분석 작업이나 큰 파일 처리 시 발생합니다.

import openai
import signal
from functools import wraps

openai.api_key = "YOUR_HOLYSHEEP_API_KEY"
openai.api_base = "https://api.holysheep.ai/v1"

타임아웃 데코레이터

class TimeoutError(Exception): pass def timeout(seconds): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): def handler(signum, frame): raise TimeoutError(f"함수 실행 시간 초과: {seconds}초") # Unix/Linux에서만 작동 try: signal.signal(signal.SIGALRM, handler) signal.alarm(seconds) result = func(*args, **kwargs) signal.alarm(0) return result except AttributeError: # Windows의 경우 time 모듈 사용 import time start = time.time() result = func(*args, **kwargs) if time.time() - start > seconds: raise TimeoutError(f"함수 실행 시간 초과: {seconds}초") return result return wrapper return decorator @timeout(30) # 30초 타임아웃 설정 def call_api_with_timeout(prompt, model="gpt-4.1", max_tokens=1000): """타임아웃이 적용된 API 호출""" response = openai.ChatCompletion.create( model=model, messages=[{"role": "user", "content": prompt}], max_tokens=max_tokens, timeout=25 # API 자체 타임아웃도 설정 ) return response

긴 문서 분석 함수

@timeout(60) # 60초 타임아웃 def analyze_long_document(document_text, model="gpt-4.1"): """ 긴 문서를 분석합니다. 토큰 수에 따라 적절히 분할합니다. """ # 토큰 수 추정 (한글은 영어 대비 약 1.5배) estimated_tokens = len(document_text) // 4 if estimated_tokens > 30000: # 긴 문서는 청크 단위로 분할 처리 print(f"긴 문서 감지 ({estimated_tokens:,} 토큰 추정). 분할 처리 시작...") chunks = split_text_into_chunks(document_text, max_tokens_per_chunk=25000) summaries = [] for i, chunk in enumerate(chunks): print(f"청크 {i+1}/{len(chunks)} 처리 중...") response = openai.ChatCompletion.create( model=model, messages=[ {"role": "system", "content": "이 텍스트의 핵심 포인트를 3문장으로 요약해주세요."}, {"role": "user", "content": chunk} ], max_tokens=200, timeout=25 ) summaries.append(response.choices[0].message.content) # 요약들을 결합하여 최종 분석 combined = "\n".join(summaries) final_response = openai.ChatCompletion.create( model=model, messages=[ {"role": "system", "content": "다음은 문서의 각 부분별 요약입니다. 이를 통합하여 전체 문서의 핵심 내용을 설명해주세요."}, {"role": "user", "content": combined} ], max_tokens=500, timeout=25 ) return final_response.choices[0].message.content else: # 일반적인 처리 response = openai.ChatCompletion.create( model=model, messages=[ {"role": "system", "content": "이 문서를 분석하고 핵심 포인트를 설명해주세요."}, {"role": "user", "content": document_text} ], max_tokens=500, timeout=25 ) return response.choices[0].message.content def split_text_into_chunks(text, max_tokens_per_chunk=25000): """텍스트를 토큰 기준 청크로 분할""" words = text.split() chunks = [] current_chunk = [] current_tokens = 0 for word in words: word_tokens = len(word) // 4 + 1 if current_tokens + word_tokens > max_tokens_per_chunk: chunks.append(" ".join(current_chunk)) current_chunk = [word] current_tokens = word_tokens else: current_chunk.append(word) current_tokens += word_tokens if current_chunk: chunks.append(" ".join(current_chunk)) return chunks

사용 예시

try: result = analyze_long_document("긴 문서 내용..." * 1000) print("분석 결과:", result) except TimeoutError as e: print(f"처리 시간 초과: {e}") except openai.error.APIError as e: print(f"API 오류: {e}")

5. 서버 장애 오류 (Server Error)

증상: 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable

원인 분석: OpenAI/Anthropic 서버 측 문제, 일시적 과부하, 또는Maintenance가 원인입니다. HolySheep AI Gateway는 이러한 장애를 자동으로 우회하여 안정성을 제공합니다.

import openai
import time
from datetime import datetime
import logging

openai.api_key = "YOUR_HOLYSHEEP_API_KEY"
openai.api_base = "https://api.holysheep.ai/v1"

로깅 설정

logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) class SmartRetryHandler: """다양한 오류 유형에 대응하는 지능형 재시도 핸들러""" ERROR_STRATEGIES = { 429: {"action": "wait", "wait_time": 30, "max_retries": 3}, # 속도 제한 500: {"action": "retry", "wait_time": 5, "max_retries": 5}, # 서버 오류 502: {"action": "retry", "wait_time": 10, "max_retries": 4}, # 게이트웨이 오류 503: {"action": "retry", "wait_time": 30, "max_retries": 3}, # 서비스 불가 504: {"action": "retry", "wait_time": 15, "max_retries": 4}, # 타임아웃 } def __init__(self): self.retry_count = defaultdict(int) self.fallback_models = ["gpt-4.1", "gpt-3.5-turbo", "claude-3-5-sonnet-20241022"] def should_retry(self, status_code, current_retries): """재시도 여부 결정""" if status_code not in self.ERROR_STRATEGIES: return False strategy = self.ERROR_STRATEGIES[status_code] return current_retries < strategy["max_retries"] def get_wait_time(self, status_code, attempt): """적절한 대기 시간 계산""" base = self.ERROR_STRATEGIES.get(status_code, {}).get("wait_time", 5) return base * (2 ** attempt) # 지수 백오프 def execute_with_retry(self, messages, model="gpt-4.1", **kwargs): """재시도 로직이 포함된 API 실행""" current_model = model current_retries = 0 while current_retries < 10: try: logger.info(f"[{datetime.now().strftime('%H:%M:%S')}] {current_model} 호출 시도 (재시도: {current_retries})") response = openai.ChatCompletion.create( model=current_model, messages=messages, **kwargs ) logger.info("API 호출 성공!") return {"success": True, "response": response, "model_used": current_model} except openai.error.RateLimitError as e: logger.warning(f"속도 제한 발생: {e}") wait_time = self.get_wait_time(429, current_retries) print(f"⏳ {wait_time}초 후 재시도...") time.sleep(wait_time) current_retries += 1 except openai.error.APIError as e: error_code = getattr(e, "http_status", 500) logger.warning(f"API 오류 (HTTP {error_code}): {e}") if not self.should_retry(error_code, current_retries): logger.error("최대 재시도 횟수 초과") return {"success": False, "error": str(e), "attempts": current_retries} # 서버 오류의 경우 폴백 모델 시도 if error_code >= 500 and current_model != self.fallback_models[0]: model_index = self.fallback_models.index(current_model) if current_model in self.fallback_models else 0 if model_index < len(self.fallback_models) - 1: current_model = self.fallback_models[model_index + 1] logger.info(f"폴백 모델 전환: {current_model}") wait_time = self.get_wait_time(error_code, current_retries) print(f"⏳ {wait_time}초 후 재시도...") time.sleep(wait_time) current_retries += 1 except Exception as e: logger.error(f"예상치 못한 오류: {type(e).__name__} - {e}") return {"success": False, "error": str(e), "attempts": current_retries} return {"success": False, "error": "최대 재시도 횟수 초과", "attempts": current_retries}

사용 예시

handler = SmartRetryHandler() messages = [ {"role": "system", "content": "당신은 유용한 어시스턴트입니다."}, {"role": "user", "content": "인공지능의 미래에 대해 설명해주세요."} ] result = handler.execute_with_retry( messages=messages, model="gpt-4.1", temperature=0.7, max_tokens=1000 ) if result["success"]: print("최종 응답:", result["response"].choices[0].message.content[:100], "...") print(f"사용된 모델: {result['model_used']}") else: print(f"실패: {result['error']} (총 시도: {result['attempts']}회)")

6. 잘못된 요청 형식 오류 (Invalid Request)

증상: 400 Bad Request, "Invalid parameter" 또는 "Missing required parameter"

원인 분석: API 파라미터 형식 오류, 지원되지 않는 파라미터 사용, 또는 잘못된 데이터 유형이 원인입니다.

import openai
from typing import List, Dict, Any, Optional

openai.api_key = "YOUR_HOLYSHEEP_API_KEY"
openai.api_base = "https://api.holysheep.ai/v1"

class RequestValidator:
    """API 요청 사전 검증 및 자동 수정"""
    
    SUPPORTED_MODELS = {
        "gpt-4.1", "gpt-4-turbo", "gpt-4", "gpt-3.5-turbo",
        "claude-3-5-sonnet-20241022", "claude-3-sonnet-20240229",
        "gemini-2.5-flash", "deepseek-v3.2"
    }
    
    VALID_PARAMETERS = {
        "model", "messages", "temperature", "max_tokens", "top_p",
        "n", "stream", "stop", "presence_penalty", "frequency_penalty",
        "user", "seed"
    }
    
    PARAMETER_RANGES = {
        "temperature": (0, 2),
        "max_tokens": (1, 32000),
        "top_p": (0, 1),
        "n": (1, 10),
        "presence_penalty": (-2, 2),
        "frequency_penalty": (-2, 2)
    }
    
    @classmethod
    def validate_message_format(cls, messages: List[Dict]) -> List[Dict]:
        """메시지 형식 검증 및 자동 수정"""
        validated = []
        for msg in messages:
            # 필수 필드 확인
            if "role" not in msg:
                raise ValueError("각 메시지에는 'role' 필드가 필수입니다")
            if "content" not in msg:
                raise ValueError("각 메시지에는 'content' 필드가 필수입니다")
            
            # 유효한 역할 확인
            valid_roles = {"system", "user", "assistant"}
            if msg["role"] not in valid_roles:
                raise ValueError(f"유효하지 않은 역할: {msg['role']}. 허용된 값: {valid_roles}")
            
            # content 타입 확인
            if not isinstance(msg["content"], str):
                if isinstance(msg["content"], list):
                    # 텍스트 블록만 허용 (이미지 등 미지원)
                    text_content = [block["text"] for block in msg["content"] if block.get("type") == "text"]
                    msg["content"] = "\n".join(text_content)
                else:
                    msg["content"] = str(msg["content"])
            
            validated.append(msg)
        
        return validated
    
    @classmethod
    def validate_and_sanitize_parameters(cls, **params) -> Dict[str, Any]:
        """파라미터 검증 및 범위 자동 수정"""
        sanitized = {}
        
        # 모델 검증
        model = params.get("model", "gpt-4.1")
        if model not in cls.SUPPORTED_MODELS:
            print(f"⚠️ 지원되지 않는 모델: {model}. gpt-4.1로 대체합니다.")
            model = "gpt-4.1"
        sanitized["model"] = model
        
        # 메시지 검증
        if "messages" not in params:
            raise ValueError("messages 파라미터는 필수입니다")
        sanitized["messages"] = cls.validate_message_format(params["messages"])
        
        # 파라미터 범위 검증 및 조정
        for param, (min_val, max_val) in cls.PARAMETER_RANGES.items():
            if param in params:
                value = params[param]
                if not isinstance(value, (int, float)):
                    print(f"⚠️ {param}의 타입 오류: {type(value)}. 기본값 사용.")
                    continue
                    
                if value < min_val:
                    print(f"⚠️ {param}이(가) 최소값({min_val})보다 작습니다. 최소값으로 조정.")
                    value = min_val
                elif value > max_val:
                    print(f"⚠️ {param}이(가) 최대값({max_val})보다 큽니다. 최대값으로 조정.")
                    value = max_val
                    
                sanitized[param] = value
        
        # 알 수 없는 파라미터 필터링
        for key in params:
            if key not in cls.VALID_PARAMETERS and key != "messages" and key != "model":
                print(f"⚠️ 알 수 없는 파라미터 무시: {key}")
        
        return sanitized

검증 데코레이터

def validate_api_request(func): """API 호출 함수의 파라미터를 자동으로 검증""" def wrapper(*args, **kwargs): try: # 키워드 인자 검증 validated_kwargs = RequestValidator.validate_and_sanitize_parameters(**kwargs) return func(*args, **validated_kwargs) except Exception as e: print(f"요청 검증 실패: {e}") raise return wrapper @validate_api_request def safe_chat_completion(**params): """검증된 API 호출만 수행하는 래퍼 함수""" return openai.ChatCompletion.create(**params)

사용 예시 - 잘못된 파라미터 자동 수정

try: # 잘못된 temperature 값 (범위 초과) response = safe_chat_completion( model="gpt-4.1", messages=[ {"role": "user", "content": "안녕하세요!"} ], temperature=5.0, # 범위 초과! (0~2) max_tokens=100000, # 범위 초과! unknown_param="test" # 알 수 없는 파라미터 ) print("정상 응답:", response.choices[0].message.content) except ValueError as e: print(f"검증 오류: {e}") except Exception as e: print(f"API 오류: {type(e).__name__}: {e}")

7. 스트리밍 응답 오류

증상: 스트리밍 모