AI API를 활용한 프로덕션 환경에서 네트워크 오류, 타임아웃, 서버 과부하로 인한 재시도는 필연적입니다. 그러나 동일한 요청이 여러 번 전송될 경우 중복 응답, 과도한 비용 발생, 데이터 불일치 등의 심각한 문제가 발생할 수 있습니다. 이 튜토리얼에서는 HolySheep AI 게이트웨이를 중심으로 AI API 멱등성 설계의 핵심 원리와 실전 구현 방법을 다룹니다.
멱등성이란 무엇인가?
멱등성(Idempotency)이란 동일한 요청을 한 번 또는 여러 번 실행しても、結果が同じであることを保证する特性です。日本語の混入は禁止されています。
정리하면, 멱등성이 보장되면 동일한 요청을 여러 번 실행해도 결과가 동일합니다. 이는 재시도가 안전한 이유이기도 합니다. AI API에서 이는 단순히 응답이 동일한 것이 아니라, 요청이 한 번만 처리되고 중복 응답이 생성되지 않음을 의미합니다.
AI API 멱등성 비교: HolySheep vs 공식 API vs 기타 서비스
| 특징 | HolySheep AI | OpenAI 공식 | 기타 중개 서비스 |
|---|---|---|---|
| 멱등성 키 지원 | O (Native) | O | 제한적 |
| 자동 중복 제거 | O (30초~7일) | O (24시간) | 서비스마다 상이 |
| 멱등성 키 TTL | 설정 가능 (30초~7일) | 고정 24시간 | 다양함 |
| 가격 | $0.42~$15/MTok | $2~$75/MTok | $1.5~$30/MTok |
| 평균 지연 시간 | 120-350ms | 200-800ms | 150-600ms |
| 재시도 로직 내장 | O (설정 가능) | X (클라이언트 구현) | 부분적 |
| 단일 API 키 다중 모델 | O | X | 제한적 |
| 한국어 기술 지원 | O | X | 제한적 |
HolySheep AI는 지금 가입하여 단일 API 키로 GPT-4.1, Claude Sonnet 4.5, Gemini 2.5 Flash, DeepSeek V3.2 등 모든 주요 모델을 멱등성 보장 하에 사용할 수 있습니다. 특히 기본 제공되는 재시도 로직과 커스텀 TTL 설정은 프로덕션 환경에서 큰 이점입니다.
멱등성 키 기반 중복 제거 아키텍처
멱등성 설계의 핵심은 요청마다 고유한 식별자를 부여하고, 서버 측에서 이를 추적하여 중복 요청을 걸러내는 것입니다. 다음은 HolySheep AI 환경에서의 멱등성 설계 아키텍처입니다.
멱등성 키 생성 전략
import hashlib
import uuid
import time
from typing import Optional
class IdempotencyKeyGenerator:
"""
AI API 멱등성 키 생성기
HolySheep AI 환경에 최적화된 키 생성 전략
"""
@staticmethod
def generate_from_request(
user_id: str,
model: str,
messages: list,
custom_suffix: Optional[str] = None
) -> str:
"""
요청 내용을 기반으로 멱등성 키 생성
Args:
user_id: 사용자 식별자
model: 사용할 모델명 (gpt-4.1, claude-sonnet-4-5, etc.)
messages: 메시지 배열
custom_suffix: 추가 식별자 (선택적)
Returns:
36자리의 UUID 형식 멱등성 키
"""
# 요청 내용에서 고유 시그니처 생성
content_hash = hashlib.sha256()
content_hash.update(user_id.encode('utf-8'))
content_hash.update(model.encode('utf-8'))
for msg in messages:
content_hash.update(f"{msg.get('role', '')}:{msg.get('content', '')}".encode('utf-8'))
if custom_suffix:
content_hash.update(custom_suffix.encode('utf-8'))
# 타임스탬프 추가 (선택적, TTL 짧을 경우)
timestamp = int(time.time() // 60) # 분 단위
# 최종 키 생성
key_input = f"{content_hash.hexdigest()[:16]}-{timestamp}"
return f"idem-{uuid.uuid5(uuid.NAMESPACE_DNS, key_input)}"
@staticmethod
def generate_simple(user_id: str, operation: str) -> str:
"""
단순 멱등성 키 생성 (간단한 작업용)
"""
return f"idem-{user_id}-{operation}-{int(time.time() // 3600)}"
사용 예시
generator = IdempotencyKeyGenerator()
채팅 요청용 멱등성 키
chat_key = generator.generate_from_request(
user_id="user_12345",
model="gpt-4.1",
messages=[
{"role": "user", "content": "Hello, explain quantum computing"}
]
)
print(f"Generated idempotency key: {chat_key}")
출력: idem-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
HolySheep AI 멱등성 클라이언트 구현
import requests
import time
from typing import Dict, Any, Optional, Callable
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
class HolySheepAIClient:
"""
HolySheep AI 멱등성 지원 API 클라이언트
자동 재시도 + 멱등성 키 관리 통합
"""
def __init__(
self,
api_key: str,
base_url: str = "https://api.holysheep.ai/v1",
timeout: int = 60,
max_retries: int = 3,
retry_delay: float = 1.0,
idempotency_ttl: int = 3600 # 1시간 (HolySheep 기본값)
):
"""
HolySheep AI 클라이언트 초기화
Args:
api_key: HolySheep AI API 키
base_url: API 기본 URL
timeout: 요청 타임아웃 (초)
max_retries: 최대 재시도 횟수
retry_delay: 재시도 지연 (초)
idempotency_ttl: 멱등성 키 유효 시간 (초)
"""
self.base_url = base_url
self.api_key = api_key
self.timeout = timeout
self.idempotency_ttl = idempotency_ttl
# 재시도 설정이 적용된 세션
self.session = requests.Session()
retry_strategy = Retry(
total=max_retries,
backoff_factor=retry_delay,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["POST", "GET"]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
self.session.mount("https://", adapter)
# 멱등성 키 캐시 (메모리 내 저장, 프로덕션에서는 Redis 권장)
self._idempotency_cache: Dict[str, Dict[str, Any]] = {}
def _get_idempotency_key(
self,
user_id: str,
operation: str,
force_new: bool = False
) -> str:
"""멱등성 키 조회 또는 생성"""
cache_key = f"{user_id}:{operation}"
if not force_new and cache_key in self._idempotency_cache:
cached = self._idempotency_cache[cache_key]
elapsed = time.time() - cached['created_at']
if elapsed < self.idempotency_ttl:
return cached['key']
# 새 키 생성
new_key = f"idem-{user_id}-{operation}-{int(time.time() * 1000)}"
self._idempotency_cache[cache_key] = {
'key': new_key,
'created_at': time.time()
}
return new_key
def chat_completions(
self,
model: str,
messages: list,
user_id: str,
temperature: float = 0.7,
max_tokens: int = 2048,
use_idempotency: bool = True
) -> Dict[str, Any]:
"""
채팅 완료 요청 (멱등성 지원)
Args:
model: 모델명 (gpt-4.1, claude-sonnet-4-5, gemini-2.5-flash, deepseek-v3.2)
messages: 메시지 배열
user_id: 멱등성 관리를 위한 사용자 ID
temperature: 응답 다양성 (0~2)
max_tokens: 최대 토큰 수
use_idempotency: 멱등성 키 사용 여부
Returns:
API 응답 딕셔너리
"""
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
idempotency_key = None
if use_idempotency:
idempotency_key = self._get_idempotency_key(
user_id=user_id,
operation=f"chat_{model.replace('/', '_')}"
)
headers["Idempotency-Key"] = idempotency_key
payload = {
"model": model,
"messages": messages,
"temperature": temperature,
"max_tokens": max_tokens
}
url = f"{self.base_url}/chat/completions"
try:
response = self.session.post(
url,
headers=headers,
json=payload,
timeout=self.timeout
)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
# 네트워크 오류 시 멱등성 키로 재시도
if use_idempotency and idempotency_key:
# 기존 키 재사용하여 재시도
return self._retry_with_same_key(
payload=payload,
idempotency_key=idempotency_key
)
raise
def _retry_with_same_key(
self,
payload: Dict[str, Any],
idempotency_key: str
) -> Dict[str, Any]:
"""동일 멱등성 키로 재시도"""
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",
"Idempotency-Key": idempotency_key
}
url = f"{self.base_url}/chat/completions"
response = self.session.post(
url,
headers=headers,
json=payload,
timeout=self.timeout
)
response.raise_for_status()
return response.json()
사용 예시
if __name__ == "__main__":
client = HolySheepAIClient(
api_key="YOUR_HOLYSHEEP_API_KEY",
max_retries=3,
retry_delay=2.0
)
response = client.chat_completions(
model="gpt-4.1",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is the capital of France?"}
],
user_id="user_12345",
temperature=0.7,
max_tokens=500
)
print(f"Response: {response['choices'][0]['message']['content']}")
print(f"Model: {response['model']}")
print(f"Usage: {response['usage']}")
Redis 기반 분산 멱등성 상태 관리
import redis
import json
import hashlib
import time
from typing import Optional, Any, Dict
from dataclasses import dataclass, asdict
from enum import Enum
class IdempotencyStatus(Enum):
"""멱등성 요청 상태"""
PENDING = "pending"
PROCESSING = "processing"
COMPLETED = "completed"
FAILED = "failed"
@dataclass
class IdempotencyRecord:
"""멱등성 레코드"""
key: str
status: str
request_hash: str
response_data: Optional[str]
created_at: float
expires_at: float
retry_count: int
class RedisIdempotencyManager:
"""
Redis 기반 분산 환경 멱등성 매니저
HolySheep AI 다중 인스턴스 환경에 최적화
"""
def __init__(
self,
redis_url: str = "redis://localhost:6379/0",
default_ttl: int = 3600,
lock_timeout: int = 30
):
self.redis = redis.from_url(redis_url)
self.default_ttl = default_ttl
self.lock_timeout = lock_timeout
# Lua 스크립트 for 원자적 작업
self._check_and_set_script = self.redis.register_script("""
local key = KEYS[1]
local lock_key = KEYS[2]
local request_hash = ARGV[1]
local ttl = tonumber(ARGV[2])
local lock_ttl = tonumber(ARGV[3])
-- 기존 레코드 확인
local existing = redis.call('GET', key)
if existing then
local data = cjson.decode(existing)
-- 요청 해시 불일치 시 에러
if data['request_hash'] ~= request_hash then
return cjson.encode({error = 'hash_mismatch', existing = data})
end
return cjson.encode({status = data['status'], data = data['response_data']})
end
-- 잠금 획득
local lock_acquired = redis.call('SET', lock_key, '1', 'NX', 'EX', lock_ttl)
if not lock_acquired then
return cjson.encode({error = 'locked'})
end
-- 새 레코드 생성
local record = {
key = key,
status = 'processing',
request_hash = request_hash,
response_data = nil,
created_at = tonumber(ARGV[4]),
expires_at = tonumber(ARGV[4]) + ttl,
retry_count = 0
}
redis.call('SET', key, cjson.encode(record), 'EX', ttl)
return cjson.encode({status = 'new', data = nil})
""")
def _generate_request_hash(
self,
model: str,
messages: list,
params: Dict[str, Any]
) -> str:
"""요청 내용 해시 생성"""
content = json.dumps({
'model': model,
'messages': messages,
'params': params
}, sort_keys=True)
return hashlib.sha256(content.encode()).hexdigest()
def check_or_create(
self,
idempotency_key: str,
model: str,
messages: list,
params: Dict[str, Any],
ttl: Optional[int] = None
) -> Dict[str, Any]:
"""
멱등성 키 확인 및 생성 (원자적 연산)
Returns:
{
'action': 'new' | 'existing' | 'processing' | 'locked',
'status': 상태값,
'data': 응답 데이터 (있는 경우)
}
"""
request_hash = self._generate_request_hash(model, messages, params)
lock_key = f"{idempotency_key}:lock"
ttl = ttl or self.default_ttl
result = self._check_and_set_script(
keys=[idempotency_key, lock_key],
args=[
request_hash,
ttl,
self.lock_timeout,
time.time()
]
)
return json.loads(result)
def store_response(
self,
idempotency_key: str,
response_data: Any,
status: str = "completed"
):
"""응답 데이터 저장"""
key = f"idem:{idempotency_key}"
existing = self.redis.get(key)
if existing:
record = json.loads(existing)
record['status'] = status
record['response_data'] = json.dumps(response_data)
ttl = max(int(record['expires_at'] - time.time()), 60)
if ttl > 0:
self.redis.setex(key, ttl, json.dumps(record))
def store_failure(
self,
idempotency_key: str,
error_message: str
):
"""실패 상태 저장"""
self.store_response(
idempotency_key,
{'error': error_message},
status="failed"
)
def get_record(self, idempotency_key: str) -> Optional[IdempotencyRecord]:
"""멱등성 레코드 조회"""
data = self.redis.get(f"idem:{idempotency_key}")
if data:
record_dict = json.loads(data)
return IdempotencyRecord(**record_dict)
return None
def invalidate(self, idempotency_key: str):
"""멱등성 레코드 무효화 (테스트용)"""
self.redis.delete(f"idem:{idempotency_key}")
self.redis.delete(f"idem:{idempotency_key}:lock")
HolySheep AI 통합 사용 예시
def holy_sheep_idempotent_request(
api_key: str,
model: str,
messages: list,
user_id: str,
params: Optional[Dict] = None
) -> Dict[str, Any]:
"""
HolySheep AI 멱등성 보장 요청 래퍼
"""
import requests
# 멱등성 매니저 초기화
manager = RedisIdempotencyManager(
redis_url="redis://localhost:6379/0",
default_ttl=3600
)
# 멱등성 키 생성
idempotency_key = f"idem-{user_id}-{model}-{hashlib.md5(json.dumps(messages).encode()).hexdigest()[:8]}"
# 멱등성 확인
result = manager.check_or_create(
idempotency_key=idempotency_key,
model=model,
messages=messages,
params=params or {}
)
if result['action'] == 'existing':
print(f"기존 응답 반환: {idempotency_key}")
return json.loads(result['data'])
if result['action'] == 'processing':
print("요청 처리 중, 기존 결과 대기...")
time.sleep(2)
record = manager.get_record(idempotency_key)
if record and record.response_data:
return json.loads(record.response_data)
if result['action'] == 'locked':
raise Exception("다른 인스턴스에서 처리 중입니다")
# 새 요청 실행
try:
response = requests.post(
"https://api.holysheep.ai/v1/chat/completions",
headers={
"Authorization": f"Bearer {api_key}",
"Idempotency-Key": idempotency_key,
"Content-Type": "application/json"
},
json={
"model": model,
"messages": messages,
**(params or {})
},
timeout=60
)
response.raise_for_status()
result_data = response.json()
# 응답 저장
manager.store_response(idempotency_key, result_data)
return result_data
except Exception as e:
manager.store_failure(idempotency_key, str(e))
raise
프로덕션 사용 예시
if __name__ == "__main__":
result = holy_sheep_idempotent_request(
api_key="YOUR_HOLYSHEEP_API_KEY",
model="gpt-4.1",
messages=[
{"role": "user", "content": "Explain machine learning in simple terms"}
],
user_id="user_12345",
params={"temperature": 0.7, "max_tokens": 1000}
)
print(f"Result: {result['choices'][0]['message']['content']}")
HolySheep AI 멱등성 설정 옵션
HolySheep AI는 다양한 멱등성 설정을 지원하여 프로덕션 환경의 요구사항에 맞게 조정할 수 있습니다.
멱등성 TTL 설정 가이드
| 사용 사례 | 권장 TTL | 이유 |
|---|---|---|
| 짧은 채팅 인터랙션 | 30초 ~ 5분 | 빠른 응답 필요, 중복 위험 낮음 |
| 표준 API 호출 | 1시간 (3600초) | balanced - HolySheep 기본값 |
| 긴 작업/배치 처리 | 24시간 | 긴 처리 시간, 높은 중복 위험 |
| 금융/결제 관련 | 7일 (최대) | 엄격한 중복 방지 필요 |
| 임시/테스트 | 5분 | 빠른 키 순환 |
실전 모니터링 및 메트릭
import logging
import time
from collections import defaultdict
from typing import Dict, List
from dataclasses import dataclass, field
@dataclass
class IdempotencyMetrics:
"""멱등성 메트릭 수집기"""
total_requests: int = 0
new_requests: int = 0
cached_responses: int = 0
processing_wait: int = 0
failed_requests: int = 0
average_retry_delay: float = 0.0
# 상세 추적
key_usage: Dict[str, int] = field(default_factory=lambda: defaultdict(int))
retry_distribution: Dict[int, int] = field(default_factory=lambda: defaultdict(int))
# 성능 추적
response_times: List[float] = []
def record_new_request(self, key: str):
self.total_requests += 1
self.new_requests += 1
self.key_usage[key] += 1
def record_cache_hit(self, key: str):
self.total_requests += 1
self.cached_responses += 1
self.key_usage[key] += 1
def record_processing_wait(self):
self.processing_wait += 1
def record_failure(self):
self.failed_requests += 1
def record_response_time(self, duration: float):
self.response_times.append(duration)
if len(self.response_times) > 1000:
self.response_times = self.response_times[-1000:]
def record_retry(self, retry_count: int):
self.retry_distribution[retry_count] += 1
def get_summary(self) -> Dict:
"""메트릭 요약 반환"""
total_time = sum(self.response_times)
count = len(self.response_times)
return {
"total_requests": self.total_requests,
"new_requests": self.new_requests,
"cached_responses": self.cached_responses,
"cache_hit_rate": (
self.cached_responses / self.total_requests * 100
if self.total_requests > 0 else 0
),
"processing_waits": self.processing_wait,
"failed_requests": self.failed_requests,
"failure_rate": (
self.failed_requests / self.total_requests * 100
if self.total_requests > 0 else 0
),
"average_response_time_ms": (
(total_time / count * 1000) if count > 0 else 0
),
"unique_keys": len(self.key_usage),
"retry_distribution": dict(self.retry_distribution),
"p95_response_time_ms": (
sorted(self.response_times)[int(count * 0.95)] * 1000
if count > 0 else 0
) if count > 0 else 0
}
class IdempotencyMonitor:
"""멱등성 모니터링 및 로깅"""
def __init__(self, logger_name: str = "idempotency"):
self.logger = logging.getLogger(logger_name)
self.metrics = IdempotencyMetrics()
self._start_time = time.time()
def log_request(
self,
idempotency_key: str,
action: str,
duration: float = 0
):
"""요청 로깅"""
if action == "new":
self.metrics.record_new_request(idempotency_key)
self.logger.info(f"NEW_REQUEST | key={idempotency_key[:20]}...")
elif action == "cache_hit":
self.metrics.record_cache_hit(idempotency_key)
self.logger.info(
f"CACHE_HIT | key={idempotency_key[:20]}... | "
f"saved_time={duration:.2f}ms"
)
elif action == "processing":
self.metrics.record_processing_wait()
self.logger.warning(f"PROCESSING_WAIT | key={idempotency_key[:20]}...")
elif action == "retry":
self.metrics.record_retry(1)
self.logger.warning(f"RETRY | key={idempotency_key[:20]}...")
def log_response(self, duration: float):
"""응답 시간 로깅"""
self.metrics.record_response_time(duration)
def get_metrics_report(self) -> str:
"""메트릭 리포트 생성"""
summary = self.metrics.get_summary()
uptime = time.time() - self._start_time
report = f"""
=== Idempotency Metrics Report ===
Uptime: {uptime:.0f} seconds
─────────────────────────────────
Total Requests: {summary['total_requests']}
- New: {summary['new_requests']}
- Cached: {summary['cached_responses']}
- Cache Hit Rate: {summary['cache_hit_rate']:.2f}%
- Failed: {summary['failed_requests']} ({summary['failure_rate']:.2f}%)
─────────────────────────────────
Performance:
- Avg Response: {summary['average_response_time_ms']:.2f}ms
- P95 Response: {summary['p95_response_time_ms']:.2f}ms
─────────────────────────────────
Unique Keys: {summary['unique_keys']}
Retry Distribution: {summary['retry_distribution']}
================================="""
return report
사용 예시
monitor = IdempotencyMonitor()
모니터링 통합 클라이언트
class MonitoredHolySheepClient(HolySheepAIClient):
"""모니터링이 추가된 HolySheep AI 클라이언트"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.monitor = IdempotencyMonitor()
def chat_completions(self, *args, **kwargs) -> Dict[str, Any]:
start_time = time.time()
idempotency_key = self._get_idempotency_key(
kwargs.get('user_id', 'unknown'),
f"chat_{kwargs.get('model', 'unknown')}"
)
try:
result = super().chat_completions(*args, **kwargs)
duration = time.time() - start_time
self.monitor.log_response(duration)
self.monitor.log_request(idempotency_key, "new", duration)
return result
except requests.exceptions.RequestException as e:
# 재시도 시나리오
self.monitor.log_request(idempotency_key, "retry")
raise
실행 예시
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
client = MonitoredHolySheepClient(
api_key="YOUR_HOLYSHEEP_API_KEY"
)
# 여러 요청 실행
for i in range(5):
try:
client.chat_completions(
model="gpt-4.1",
messages=[{"role": "user", "content": f"Test {i}"}],
user_id="user_12345"
)
except Exception as e:
print(f"Error: {e}")
# 메트릭 출력
print(client.monitor.get_metrics_report())
자주 발생하는 오류와 해결책
1. 멱등성 키 충돌 오류 (409 Conflict)
# ❌ 잘못된 접근: 동일한 키로 다른 요청 전송
payload1 = {"model": "gpt-4.1", "messages": [{"role": "user", "content": "Hello"}]}
payload2 = {"model": "gpt-4.1", "messages": [{"role": "user", "content": "Hi"}]}
같은 키 사용 시 409 오류 발생
headers1 = {"Idempotency-Key": "same-key-123", "Authorization": f"Bearer {API_KEY}"}
headers2 = {"Idempotency-Key": "same-key-123", "Authorization": f"Bearer {API_KEY}"}
✅ 올바른 접근: 요청 내용에 기반한 고유 키 생성
def generate_unique_key(user_id: str, model: str, messages: list) -> str:
"""요청 내용을 해싱하여 고유 키 생성"""
import hashlib
content = json.dumps({"model": model, "messages": messages}, sort_keys=True)
hash_value = hashlib.sha256(content.encode()).hexdigest()[:16]
return f"idem-{user_id}-{hash_value}-{int(time.time() // 300)}"
headers1 = {"Idempotency-Key": generate_unique_key("user_1", "gpt-4.1", payload1["messages"])}
headers2 = {"Idempotency-Key": generate_unique_key("user_1", "gpt-4.1", payload2["messages"])
2. 재시도 시 멱등성 키 누락
# ❌ 잘못된 접근: 재시도 시 새 키 생성
def bad_retry(url, payload, api_key):
headers = {"Authorization": f"Bearer {api_key}"}
# 첫 요청
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 500:
# ❌ 재시도 시 새 키 생성 -> 중복 처리 발생!
new_headers = {"Authorization": f"Bearer {api_key}"}
return requests.post(url, headers=new_headers, json=payload)
✅ 올바른 접근: 재시도 시 기존 키 재사용
def good_retry(url, payload, api_key, max_retries=3):
idempotency_key = f"idem-{uuid.uuid4()}"
headers = {
"Authorization": f"Bearer {api_key}",
"Idempotency-Key": idempotency_key # 최초 요청时就确定
}
for attempt in range(max_retries):
try:
response = requests.post(url, headers=headers, json=payload, timeout=30)
if response.status_code == 200:
return response.json()
if response.status_code >= 500: # 서버 오류만 재시도
continue
response.raise_for_status()
except (requests.exceptions.Timeout, requests.exceptions.ConnectionError):
# 네트워크 오류 시에도 동일한 키 사용
headers["Idempotency-Key"] = idempotency_key
continue
raise Exception("Max retries exceeded")
3. 멱등성 TTL 만료로 인한 데이터 불일치
# ❌ 잘못된 접근: 긴 TTL 의존
TTL 24시간 후 같은 키로 요청 시 서버는 새 요청으로 처리
하지만 클라이언트는 이전 응답을 캐시에서 반환 -> 불일치!
✅ 올바른 접근: TTL 고려한 설계
class TTLawareClient:
def __init__(self, api_key, base_url):
self.api_key = api_key
self.base_url = base_url
self.ttl = 3600 # HolySheep 기본 TTL
self.local_cache = {}
def request(self, key, payload):
cache_key = f"{key}:{hash_payload(payload)}"
if cache_key in self.local_cache:
cached = self.local_cache[cache_key]
age = time.time() - cached['timestamp']
# TTL의 80% 시점에서 fresh请求
if age > self.ttl * 0.8:
# 이전 응답 반환하면서 새 요청 병행
self._background_refresh(cache_key, payload)
return cached['response']
elif age < self.ttl:
return cached['response']
# 새 요청
response = self._do_request(key, payload)
self.local_cache[cache_key] = {
'response': response,
'timestamp': time.time()
}
return response
def _background_refresh(self, cache_key, payload):
"""백그라운드에서 TTL 만료 전에 미리 갱신