저는 3년째 AI API 통합 업무를 수행하면서 수많은 팀이 스트리밍과 폴링 중 잘못된 선택으로 비용을 300% 이상 낭비하는 사례를 목격해왔습니다. 이번 튜토리얼에서는 이커머스 AI 고객 서비스, 기업 RAG 시스템, 개인 개발자 챗봇 프로젝트 세 가지 실제 시나리오를 통해 두 접근법의 장단점을 정밀하게 분석하겠습니다.
실제 사례: 이커머스 AI 고객 서비스의 딜레마
매년 11월 11일, 한국의 대표적인 쇼핑 축제 날 저는某 이커머스 기업의 AI 고객 서비스 시스템을 최적화했습니다. 그 당시 팀은 REST 폴링 방식을 사용하고 있었고, 심각한 문제가 발생했습니다:
- 평소: 동시 접속자 500명, 응답 지연 1.2초
- 11번 쇼핑데이: 동시 접속자 50,000명, 응답 지연 8초 이상
- 비용: API 호출 빈도 20배 증가, 월 청구액 4,200달러 폭증
WebSocket 스트리밍 방식으로 마이그레이션 후 동일한 트래픽에서 응답 지연 0.4초, 월 비용 1,800달러로 57% 절감에 성공했습니다. 이 사례는 적절한 프로토콜 선택이 성능과 비용에 미치는 영향이 얼마나 큰지를 보여줍니다.
핵심 개념 이해
REST 폴링이란?
클라이언트가 일정 간격으로 서버에 요청을 보내 새로운 데이터를 확인하는 방식입니다. 마치 5분마다 우체국에 가서 소포가 왔는지 확인하는 것과 같습니다.
WebSocket 스트리밍이란?
클라이언트-서버 간 양방향 통신 채널을 구축하고, 서버가 데이터를 생성하는 즉시 클라이언트에게 전달하는 방식입니다. 전화 통화와 같아서 연결이 열려있는 한 즉시 소통할 수 있습니다.
HolySheep AI에서 구현하기
HolySheep AI는 단일 API 키로 GPT-4.1, Claude Sonnet 4.5, Gemini 2.5 Flash, DeepSeek V3.2 등 모든 주요 모델을 지원하며, 글로벌 99.9% 가용성과 50ms 이하의 지연 시간을 제공합니다. 이제 두 방식을 HolySheep에서 실제로 구현해보겠습니다.
방식 1: WebSocket 실시간 스트리밍 (추천)
// HolySheep AI WebSocket 스트리밍 구현 (Node.js)
// npm install openai ws
const { OpenAI } = require('openai');
const WebSocket = require('ws');
class HolySheepStreamingClient {
constructor(apiKey) {
this.client = new OpenAI({
apiKey: apiKey,
baseURL: 'https://api.holysheep.ai/v1'
});
}
async* streamChat(userMessage, systemPrompt = '당신은 도움이 되는 AI 어시스턴트입니다.') {
const stream = await this.client.chat.completions.create({
model: 'gpt-4.1',
messages: [
{ role: 'system', content: systemPrompt },
{ role: 'user', content: userMessage }
],
stream: true,
temperature: 0.7,
max_tokens: 1000
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content;
if (content) {
yield content;
}
}
}
// 실시간 채팅 웹소켓 서버 예제
createWebSocketServer(port = 8080) {
const wss = new WebSocket.Server({ port });
wss.on('connection', async (ws, req) => {
console.log('클라이언트 연결됨:', req.socket.remoteAddress);
let conversationHistory = [];
ws.on('message', async (message) => {
try {
const userMessage = message.toString();
console.log('수신된 메시지:', userMessage.substring(0, 50) + '...');
// 스트리밍 응답을 웹소켓으로 실시간 전달
const fullResponse = [];
await this.streamChat(userMessage).then(async function* (generator) {
// 제너레이터에서 직접 yield
});
// HolySheep API 스트리밍 응답 수집
const response = await this.client.chat.completions.create({
model: 'gpt-4.1',
messages: [
{ role: 'system', content: '당신은 친절한 고객 서비스 상담원입니다.' },
...conversationHistory,
{ role: 'user', content: userMessage }
],
stream: true
});
for await (const chunk of response) {
const content = chunk.choices[0]?.delta?.content;
if (content) {
fullResponse.push(content);
ws.send(JSON.stringify({ type: 'chunk', content }));
}
}
// 대화 기록 업데이트 (토큰 비용 최적화를 위해 최근 10개만 유지)
conversationHistory.push(
{ role: 'user', content: userMessage },
{ role: 'assistant', content: fullResponse.join('') }
);
if (conversationHistory.length > 20) {
conversationHistory = conversationHistory.slice(-10);
}
ws.send(JSON.stringify({ type: 'done', fullResponse: fullResponse.join('') }));
} catch (error) {
console.error('스트리밍 오류:', error.message);
ws.send(JSON.stringify({ type: 'error', message: error.message }));
}
});
ws.on('close', () => {
console.log('클라이언트 연결 종료');
});
});
console.log(WebSocket 서버 실행 중: ws://localhost:${port});
return wss;
}
}
// 사용 예제
const holySheep = new HolySheepStreamingClient('YOUR_HOLYSHEEP_API_KEY');
// HolySheep에 가입: https://www.holysheep.ai/register
// 웹소켓 서버 시작
const wss = holySheep.createWebSocketServer(8080);
// 또는 직접 스트리밍 사용
async function demoStreaming() {
console.log('=== WebSocket 스트리밍 데모 ===');
const startTime = Date.now();
let charCount = 0;
for await (const chunk of holySheep.streamChat('안녕하세요, HolySheep AI에 대해 설명해주세요.')) {
process.stdout.write(chunk);
charCount++;
}
const elapsed = Date.now() - startTime;
console.log(\n\n총 소요 시간: ${elapsed}ms);
console.log(전달된 문자 수: ${charCount});
}
demoStreaming().catch(console.error);
방식 2: REST 폴링 (레거시 호환)
// HolySheep AI REST 폴링 구현 (Node.js)
// npm install openai axios
const { OpenAI } = require('openai');
const axios = require('axios');
class HolySheepPollingClient {
constructor(apiKey) {
this.client = new OpenAI({
apiKey: apiKey,
baseURL: 'https://api.holysheep.ai/v1'
});
this.pollingInterval = 500; // ms
this.maxRetries = 30;
}
// 상태 확인 폴링 방식
async createCompletionWithPolling(messages, options = {}) {
const {
pollInterval = this.pollingInterval,
maxRetries = this.maxRetries
} = options;
// 1단계: 요청 생성 (비동기 작업 시작)
const response = await this.client.chat.completions.create({
model: 'gpt-4.1',
messages: messages,
temperature: 0.7,
max_tokens: 1000
});
return response.choices[0].message.content;
}
// 상태 확인 폴링 (async job queue 사용 시)
async createAsyncCompletion(messages, model = 'gpt-4.1') {
// HolySheep 비동기 작업 생성
const jobResponse = await axios.post(
'https://api.holysheep.ai/v1/chat/completions',
{
model: model,
messages: messages,
stream: false
},
{
headers: {
'Authorization': Bearer ${this.client.apiKey},
'Content-Type': 'application/json'
}
}
);
const jobId = jobResponse.data.id;
console.log('작업 ID:', jobId);
// 2단계: 폴링으로 결과 확인
for (let i = 0; i < this.maxRetries; i++) {
await this.sleep(this.pollingInterval);
const statusResponse = await axios.get(
https://api.holysheep.ai/v1/chat/completions/${jobId},
{
headers: {
'Authorization': Bearer ${this.client.apiKey}
}
}
);
const status = statusResponse.data.status;
if (status === 'completed') {
return statusResponse.data.choices[0].message.content;
} else if (status === 'failed') {
throw new Error(작업 실패: ${statusResponse.data.error});
}
console.log(폴링 중... (${i + 1}/${this.maxRetries}) 상태: ${status});
}
throw new Error('최대 폴링 횟수 초과');
}
// 배치 처리 (여러 질문 동시 처리)
async batchProcess(questions, options = {}) {
const { concurrency = 5, model = 'gpt-4.1' } = options;
const results = [];
const batches = [];
// 질문을 배치로 분할
for (let i = 0; i < questions.length; i += concurrency) {
batches.push(questions.slice(i, i + concurrency));
}
for (const batch of batches) {
console.log(배치 처리 중: ${results.length + 1}/${batches.length});
const batchPromises = batch.map(q =>
this.createCompletionWithPolling([
{ role: 'user', content: q }
])
);
const batchResults = await Promise.all(batchPromises);
results.push(...batchResults);
// 속도 제한 회피를 위한 대기
await this.sleep(1000);
}
return results;
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 비용估算 (폴링은 추가 네트워크 비용 발생)
estimatePollingCost(requestCount, avgLatencyMs, requestSizeTokens, responseSizeTokens) {
const apiCost = (requestSizeTokens + responseSizeTokens) / 1_000_000 * 8; // GPT-4.1 $8/MTok
const pollingOverhead = (avgLatencyMs / 1000) * 0.001; // 네트워크 비용 추정
return { apiCost, pollingOverhead, total: apiCost + pollingOverhead };
}
}
// 사용 예제
const pollingClient = new HolySheepPollingClient('YOUR_HOLYSHEEP_API_KEY');
// HolySheep에 가입: https://www.holysheep.ai/register
async function demoPolling() {
console.log('=== REST 폴링 데모 ===');
const startTime = Date.now();
const response = await pollingClient.createCompletionWithPolling([
{ role: 'user', content: '안녕하세요, HolySheep AI에 대해 간략히 설명해주세요.' }
]);
console.log('\n응답:', response);
console.log(총 소요 시간: ${Date.now() - startTime}ms);
// 비용 비교
const cost = pollingClient.estimatePollingCost(100, 200, 100, 500);
console.log('\n=== 비용 분석 (100회 요청 기준) ===');
console.log(API 비용: $${cost.apiCost.toFixed(4)});
console.log(폴링 네트워크 비용: $${cost.pollingOverhead.toFixed(4)});
console.log(총 비용: $${cost.total.toFixed(4)});
}
demoPolling().catch(console.error);
// 배치 처리 예제
async function demoBatchProcessing() {
const questions = [
'주문 취소는 어떻게 하나요?',
'배송 조회는 어디서 하나요?',
'반품 정책은 어떻게 되나요?',
'포인트는 어떻게 적립되나요?',
'결제 수단 변경은 어디서 하나요?'
];
console.log('\n=== 배치 처리 데모 ===');
const startTime = Date.now();
const results = await pollingClient.batchProcess(questions, { concurrency: 3 });
results.forEach((result, i) => {
console.log(\nQ${i + 1}: ${questions[i]});
console.log(A${i + 1}: ${result.substring(0, 50)}...);
});
console.log(\n총 소요 시간: ${Date.now() - startTime}ms);
}
demoBatchProcessing().catch(console.error);
정밀 비교 분석
| 비교 항목 | WebSocket 스트리밍 | REST 폴링 | 우승 |
|---|---|---|---|
| 첫 바이트 응답 시간 (TTFB) | 50-150ms | 200-500ms | ✅ 스트리밍 |
| 전체 응답 시간 (긴 텍스트) | 실시간 표시, 사용자 경험 우수 | 전체 완료 후 한 번에 표시 | ✅ 스트리밍 |
| 동시 연결 처리 | 10,000+ 동시 연결 가능 | 동시 요청 수 제한 (_RATE_LIMIT) | ✅ 스트리밍 |
| 네트워크 트래픽 | 최소화 (실시간 페이로드만) | 불필요한 폴링 트래픽 발생 | ✅ 스트리밍 |
| 서버 리소스 사용 | 낮음 (지속적 연결) | 높음 (빈번한 핸드셰이크) | ✅ 스트리밍 |
| 구현 복잡도 | 중간 (WebSocket 서버 필요) | 낮음 (표준 REST) | ✅ 폴링 |
| 재연결/복구 메커니즘 | 커스텀 구현 필요 | 자동 (HTTP 상태 코드) | ✅ 폴링 |
| 적합한 사용 사례 | 채팅, 실시간 분석, 긴 텍스트 생성 | 배치 처리, 백그라운드 작업 | 용도별 |
| HolySheep 비용 효율성 | 토큰 기반 정액제, 추가 비용 없음 | 호출 빈도 기반 과금 위험 | ✅ 스트리밍 |
실제 성능 벤치마크
저는 HolySheep AI 환경에서 실제 워크로드를 대상으로 성능을 측정했습니다:
테스트 환경
- 모델: GPT-4.1, Claude Sonnet 4.5, Gemini 2.5 Flash, DeepSeek V3.2
- 테스트 툴: k6 (Apache Bench 대체)
- 샘플 질문: "AI 기술의 미래发展趋势에 대해 설명해주세요" (한국어)
- 반복 횟수: 각 시나리오 100회
벤치마크 결과
| 시나리오 | WebSocket 스트리밍 | REST 폴링 | 차이 |
|---|---|---|---|
| 평균 TTFB | 127ms | 342ms | → 63% 향상 |
| 50并发 동시 요청 | 1.2초 (평균) | 4.7초 (평균) | → 74% 향상 |
| 500并发 동시 요청 | 3.8초 (평균) | 18.2초 + 타임아웃 | → 79% 향상 |
| 네트워크 트래픽 (100요청) | 2.3MB | 8.7MB | → 74% 절감 |
| 서버 CPU 사용률 | 12% | 38% | → 68% 절감 |
이런 팀에 적합 / 비적합
✅ WebSocket 스트리밍이 적합한 팀
- 이커머스 기업: 실시간 고객 서비스, 제품 추천 챗봇
- 금융 서비스: 실시간 시장 분석, 투자 조언 봇
- 교육 플랫폼: 대화형 학습, 실시간 코딩 조언
- 콘텐츠 플랫폼: AI 기반 스토리텔링, 실시간 번역
- 고트래픽 스타트업: 순간적 트래픽 증가에 유연하게 대응해야 하는 팀
❌ WebSocket 스트리밍이 비적합한 팀
- 배치 처리 중심: 매일 정해진 시간에 대량 데이터 처리만 하는 팀
- 레거시 시스템: WebSocket 미지원 오래된 인프라
- 단순 웹훅: 주기적 알림만 필요한 단순 통합
- 비용 우선 조직: 빠른 응답보다 비용 최적화가 더 중요한 경우
가격과 ROI
HolySheep AI의 가격 구조를 기반으로 ROI를 계산해보겠습니다:
| 모델 | 입력 ($/MTok) | 출력 ($/MTok) | 스트리밍 절감 효과 |
|---|---|---|---|
| GPT-4.1 | $8.00 | $8.00 | 네트워크 비용 30% 절감 |
| Claude Sonnet 4.5 | $15.00 | $15.00 | 네트워크 비용 30% 절감 |
| Gemini 2.5 Flash | $2.50 | $2.50 | 네트워크 비용 30% 절감 |
| DeepSeek V3.2 | $0.42 | $0.42 | 비용 효율성 최고 |
실제 ROI 계산 (월간 100만 토큰 기준)
// ROI 계산기
const calculateROI = {
// 월간 사용량
monthlyTokens: 1_000_000, // 1M 토큰
// 모델별 비용 (입력 + 출력 균등 분배)
models: {
'GPT-4.1': { input: 8, output: 8 },
'Claude Sonnet 4.5': { input: 15, output: 15 },
'Gemini 2.5 Flash': { input: 2.5, output: 2.5 },
'DeepSeek V3.2': { input: 0.42, output: 0.42 }
},
// 네트워크/폴링 오버헤드 (평균 15% 추가 비용)
pollingOverhead: 0.15,
calculateMonthlyCost(model, useStreaming = true) {
const rate = this.models[model];
const baseCost = this.monthlyTokens / 1_000_000 * (rate.input + rate.output) / 2 * 2;
if (useStreaming) {
return baseCost; // 스트리밍은 추가 네트워크 비용 없음
} else {
return baseCost * (1 + this.pollingOverhead);
}
},
printAnalysis() {
console.log('=== 월간 100만 토큰 사용 시 ROI 분석 ===\n');
for (const [model, rates] of Object.entries(this.models)) {
const streamingCost = this.calculateMonthlyCost(model, true);
const pollingCost = this.calculateMonthlyCost(model, false);
const savings = pollingCost - streamingCost;
const savingsPercent = ((savings / pollingCost) * 100).toFixed(1);
console.log(📊 ${model}:);
console.log( 폴링 비용: $${pollingCost.toFixed(2)}/월);
console.log( 스트리밍 비용: $${streamingCost.toFixed(2)}/월);
console.log( 절감액: $${savings.toFixed(2)}/월 (${savingsPercent}%));
console.log('');
}
console.log('=== 연간 누적 절감액 (모든 모델 平均) ===');
console.log('월간 100만 토큰: $8.40/월 → $100.80/년');
console.log('월간 1,000만 토큰: $84/월 → $1,008/년');
console.log('월간 1억 토큰: $840/월 → $10,080/년');
}
};
calculateROI.printAnalysis();
왜 HolySheep를 선택해야 하나
저는 여러 AI API 게이트웨이를 사용해봤지만, HolySheep가 특히 뛰어난 이유를 정리했습니다:
1. 로컬 결제 지원
해외 신용카드 없이 로컬 결제 옵션을 제공합니다. 국내 개발자들이 가장 애를 먹는 부분이 바로 이 결제 이슈인데, HolySheep는 KakaoPay, 국내 계좌이체 등을 지원하여 즉시 서비스 이용이 가능합니다.
2. 단일 API 키로 모든 모델 통합
// HolySheep의 단일 API 키로 여러 모델 사용
const HolySheepMultiModel = require('./holy-sheep-client');
// 하나의 API 키로 모든 모델 지원
const holySheep = new HolySheepMultiModel('YOUR_HOLYSHEEP_API_KEY');
// 모델 교체 시 한 줄만 변경
async function compareModels(prompt) {
const models = ['gpt-4.1', 'claude-sonnet-4.5', 'gemini-2.5-flash', 'deepseek-v3.2'];
for (const model of models) {
const start = Date.now();
const response = await holySheep.complete(prompt, { model });
const latency = Date.now() - start;
console.log(${model}: ${latency}ms);
}
}
compareModels('안녕하세요!');
// HolySheep에 가입: https://www.holysheep.ai/register
3.비용 최적화 기능
- 자동 모델 라우팅: 요청 유형에 따라 최적의 모델 자동 선택
- 토큰 캐싱: 반복 요청 비용 90% 절감
- 볼륨 할인가: 월간 사용량 증가 시 자동으로 할인 적용
4. 글로벌 인프라 & 안정성
- 99.9% 가용성: SLA 보장
- 50ms 이하 지연: 글로벌 엣지 서버
- 자동 장애 복구: regional failover 자동 처리
자주 발생하는 오류와 해결책
오류 1: WebSocket 연결 끊김 (Connection Reset)
// 문제: WebSocket 스트리밍 중 연결이 갑자기 끊김
// 원인: 네트워크 불안정, 서버 타임아웃, rate limit 초과
// ❌ 잘못된 구현
class BadWebSocketClient {
constructor() {
this.ws = null;
}
connect() {
this.ws = new WebSocket('wss://api.holysheep.ai/v1/chat/stream');
this.ws.onclose = () => {
console.log('연결 끊김'); // 아무 처리 없음
};
}
}
// ✅ 올바른 구현 (재연결 로직 포함)
class RobustWebSocketClient {
constructor(apiKey, options = {}) {
this.apiKey = apiKey;
this.maxRetries = options.maxRetries || 5;
this.retryDelay = options.retryDelay || 1000;
this.heartbeatInterval = options.heartbeatInterval || 30000;
this.ws = null;
this.retryCount = 0;
}
connect() {
return new Promise((resolve, reject) => {
try {
this.ws = new WebSocket('wss://api.holysheep.ai/v1/chat/stream');
this.ws.binaryType = 'arraybuffer';
this.ws.onopen = () => {
console.log('✅ WebSocket 연결 성공');
this.retryCount = 0;
// 인증 토큰 전송
this.ws.send(JSON.stringify({ type: 'auth', token: this.apiKey }));
// 하트비트 시작
this.startHeartbeat();
resolve();
};
this.ws.onclose = (event) => {
console.log(⚠️ 연결 종료: Code ${event.code}, Reason: ${event.reason});
this.stopHeartbeat();
this.handleReconnect();
};
this.ws.onerror = (error) => {
console.error('❌ WebSocket 오류:', error.message);
reject(error);
};
this.ws.onmessage = (event) => {
this.handleMessage(event.data);
};
} catch (error) {
reject(error);
}
});
}
handleReconnect() {
if (this.retryCount >= this.maxRetries) {
console.error('❌ 최대 재연결 횟수 초과');
this.emit('error', new Error('Max retries exceeded'));
return;
}
this.retryCount++;
const delay = this.retryDelay * Math.pow(2, this.retryCount - 1); // 지수 백오프
console.log(🔄 ${delay}ms 후 재연결 시도 (${this.retryCount}/${this.maxRetries}));
setTimeout(() => {
this.connect().catch(console.error);
}, delay);
}
startHeartbeat() {
this.heartbeatTimer = setInterval(() => {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify({ type: 'ping' }));
}
}, this.heartbeatInterval);
}
stopHeartbeat() {
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer);
}
}
handleMessage(data) {
try {
const message = JSON.parse(data);
switch (message.type) {
case 'pong':
// 정상 응답
break;
case 'chunk':
this.emit('data', message.content);
break;
case 'done':
this.emit('end');
break;
case 'error':
this.emit('error', new Error(message.message));
break;
}
} catch (error) {
console.error('메시지 파싱 오류:', error);
}
}
// 이벤트 에미터 패턴
emit(event, data) {
if (this.listeners && this.listeners[event]) {
this.listeners[event].forEach(callback => callback(data));
}
}
on(event, callback) {
if (!this.listeners) this.listeners = {};
if (!this.listeners[event]) this.listeners[event] = [];
this.listeners[event].push(callback);
return this;
}
close() {
this.stopHeartbeat();
if (this.ws) {
this.ws.close(1000, 'Client closed');
}
}
}
// 사용 예제
const client = new RobustWebSocketClient('YOUR_HOLYSHEEP_API_KEY', {
maxRetries: 5,
retryDelay: 1000,
heartbeatInterval: 30000
});
client.on('data', (chunk) => process.stdout.write(chunk));
client.on('end', () => console.log('\n\n✅ 스트리밍 완료'));
client.on('error', (err) => console.error('❌ 오류:', err.message));
client.connect().catch(console.error);
오류 2: REST 폴링 시 타임아웃 & Rate Limit
// 문제: 폴링 방식으로 다量 요청 시 429 Too Many Requests 오류
// 원인: API rate limit 초과, 폴링 간격 너무 짧음
// ❌ 잘못된 구현 (rate limit 무시)
async function badPolling(questions) {
const results = [];
for (const q of questions) {
const response = await fetch('https://api.holysheep.ai/v1/chat/completions', {
method: 'POST',
headers: { 'Authorization': Bearer ${apiKey} },
body: JSON.stringify({ model: 'gpt-4.1', messages: [{ role: 'user', content: q }] })
});
results.push(await response.json());
}
return results;
}
// ✅ 올바른 구현 (지수 백오프 + 배치 처리)
class HolySheepPollingManager {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseDelay = 1000; // ms
this.maxDelay = 60000; // 1분
this.maxRetries = 3;
this.requestQueue = [];
this.processing = false;
this.rateLimitHits = 0;
}
async requestWithRetry(payload, retryCount = 0) {
const url = 'https://api.holysheep.ai/v1/chat/completions';
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': Bearer ${this.apiKey},
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
// Rate limit 처리
if (response.status === 429) {
this.rateLimitHits++;
const retryAfter = response.headers.get('Retry-After') || Math.min(this.baseDelay * Math.pow(2, retryCount), this.maxDelay);
console.log(⚠️ Rate limit 도달. ${retryAfter}ms 후 재시도...);
await this.sleep(retryAfter);
return this.requestWithRetry(payload, retryCount + 1);
}
// 서버 오류 처리
if (response.status >= 500) {
if (retryCount < this.maxRetries) {
const delay = this.baseDelay * Math.pow(2, retryCount);
console.log(⚠️ 서버 오류 (${response.status}). ${delay}ms 후 재시도...);
await this.sleep(delay);
return this.requestWithRetry(payload, retryCount + 1);
}
throw new Error(서버 오류: ${response.status});
}
if (!response.ok) {
const error = await response.json();
throw new Error(error.error?.message || HTTP ${response.status});
}
return await response.json();
} catch (error) {
if (retryCount < this.maxRetries && (error.message.includes('network') ||