저는 경기도 수원에 위치한 스마트팜 스타트업에서 3년째 AI 솔루션을 개발하고 있는 엔지니어입니다. 이번에 HolySheep AI를 도입하여 소의 체중 추정, 사료 배합 최적화, 그리고 다중 모델 장애 대응 파이프라인을 구축한 경험을 공유합니다. 해외 신용카드 없이 로컬 결제가 가능하고 단일 API 키로 여러 모델을 관리할 수 있다는 점이 국내 개발자에게 얼마나 큰 장점인지 체감했습니다.
프로젝트 개요: 스마트 축산 사료 스케줄링 시스템
실시간 영상에서 소의 체중을 추정하고, 성장 단계와 사료 가격에 따라 최적의 사료 배합을 제안하며, 모델 장애 시 자동으로 대체 모델로 전환하는 시스템을 구축했습니다. 이 시스템은 3가지 핵심 AI 기능을 통합합니다:
- Gemini 2.5 Flash: CCTV 영상 프레임 분석 → 체중 추정
- Claude Sonnet 4: 사료 성분·가격 데이터 → 사료 전략 수립
- 다중 모델 Fallback: 주력 모델 장애 시 자동 전환
왜 HolySheep AI인가?
기존에 직접 Anthropic API와 Google AI API를 연동했으나 세 가지 문제에 직면했습니다. 첫째, 해외 신용카드 결제 한계로 매달 충전이 번거로웠습니다. 둘째, 각 모델의 rate limit과 과금이 다르며 별도 모니터링이 필요했습니다. 셋째, 특정 모델 장애 시 수동으로 코드를 수정해야 하는 불편함이 있었습니다. HolySheep AI는 이 세 가지 문제를 단일 플랫폼에서 모두 해결해주었습니다.
지금 가입하면 무료 크레딧을 받을 수 있어 프로토타입 테스트에 즉시 활용할 수 있습니다.
HolySheep AI vs 경쟁 플랫폼 비교
| 평가 항목 | HolySheep AI | 직접 API 연동 | 기타 게이트웨이 |
|---|---|---|---|
| Gemini 2.5 Flash | $2.50/MTok | $2.50/MTok | $3.00~4.00/MTok |
| Claude Sonnet 4 | $15/MTok | $15/MTok | $18~22/MTok |
| DeepSeek V3.2 | $0.42/MTok | $0.42/MTok | $0.60+/MTok |
| 결제 편의성 | ★★★★★ 로컬 결제 지원 | ★★★★☆ 해외 신용카드 | ★★☆☆☆ 제한적 |
| 평균 응답 지연 | 820ms | 750ms | 1,200ms |
| 다중 모델 Fallback | ★★★★★ 내장 지원 | ★★☆☆☆ 수동 구현 | ★★★☆☆ 기본 지원 |
| 콘솔 UX | ★★★★☆ 직관적 | N/A | ★★★☆☆ 보통 |
| 免费 크레딧 | ★★★★★ 가입 시 제공 | ★★☆☆☆ 제한적 | ★★★☆☆ 일부 |
실전 구현: HolySheep AI SDK 활용 코드
아래는 제가 실제 프로덕션에서 사용 중인 HolySheep AI 연동 코드입니다. base_url을 정확히 https://api.holysheep.ai/v1로 설정하고, YOUR_HOLYSHEEP_API_KEY를 HolySheep 콘솔에서 발급받은 키로 교체하면 바로 동작합니다.
1. Gemini 2.5 Flash를 활용한 소 체중 추정
"""
HolySheep AI - Gemini 2.5 Flash 체중 추정 모듈
CCTV 영상에서 소의 외형을 분석하여 체중을 추정합니다.
"""
import base64
import requests
from PIL import Image
from io import BytesIO
HOLYSHEEP_API_KEY = "YOUR_HOLYSHEEP_API_KEY"
BASE_URL = "https://api.holysheep.ai/v1"
def encode_image_to_base64(image_path: str) -> str:
"""이미지를 base64로 인코딩"""
with Image.open(image_path) as img:
buffered = BytesIO()
img.save(buffered, format="JPEG", quality=85)
return base64.b64encode(buffered.getvalue()).decode("utf-8")
def estimate_cattle_weight(image_path: str, breed: str = "한우") -> dict:
"""
Gemini 2.5 Flash를 사용하여 소 체중 추정
응답 시간 목표: 1,200ms 이하
비용: $2.50/1M 토큰
"""
image_b64 = encode_image_to_base64(image_path)
system_prompt = f"""당신은 축산 전문가입니다.
주어진 소 사진을 분석하여 체중을 추정하세요.
품종: {breed}
응답 형식: {{"estimated_weight_kg": 숫자, "confidence": 0~1, "reasoning": "설명"}}
"""
user_prompt = "이 소의 체중을 추정해주세요. 품종 특성과 체형 상태를 고려하세요."
payload = {
"model": "gemini-2.5-flash-preview-05-20",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": user_prompt},
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{image_b64}"
}
}
]
}
],
"system": system_prompt,
"max_tokens": 500,
"temperature": 0.3
}
headers = {
"Authorization": f"Bearer {HOLYSHEEP_API_KEY}",
"Content-Type": "application/json"
}
response = requests.post(
f"{BASE_URL}/chat/completions",
json=payload,
headers=headers,
timeout=15
)
if response.status_code == 200:
result = response.json()
content = result["choices"][0]["message"]["content"]
usage = result.get("usage", {})
# 비용 계산: 입력 + 출력 토큰
input_tokens = usage.get("prompt_tokens", 0)
output_tokens = usage.get("completion_tokens", 0)
cost_usd = (input_tokens + output_tokens) / 1_000_000 * 2.50
print(f"[성공] 체중 추정 완료")
print(f"[비용] ${cost_usd:.4f} (입력: {input_tokens}, 출력: {output_tokens})")
print(f"[지연] {result.get('response_ms', 0)}ms")
return {
"status": "success",
"data": content,
"cost_usd": cost_usd,
"latency_ms": result.get("response_ms", 0)
}
else:
print(f"[오류] {response.status_code}: {response.text}")
return {"status": "error", "message": response.text}
사용 예시
result = estimate_cattle_weight("cattle_001.jpg", breed="한우")
print(result)
2. Claude Sonnet 4를 활용한 사료 전략 최적화
"""
HolySheep AI - Claude Sonnet 4 사료 배합 최적화 모듈
가격, 영양성분, 사육 환경 데이터를 기반으로 최적 사료 전략 수립
"""
import requests
from datetime import datetime
HOLYSHEEP_API_KEY = "YOUR_HOLYSHEEP_API_KEY"
BASE_URL = "https://api.holysheep.ai/v1"
def optimize_feed_strategy(
cattle_data: list,
feed_prices: dict,
available_feeds: list
) -> dict:
"""
Claude Sonnet 4를 사용하여 사료 전략 최적화
응답 시간 목표: 2,500ms 이하
비용: $15/1M 토큰
"""
system_prompt = """당신은 축산 영양 전문가입니다.
주어진 데이터 기반으로 비용 효율적이면서도 영양 균형 잡힌 사료 배합 전략을 수립하세요.
응답은 반드시 JSON 형식으로 제공하세요.
"""
user_prompt = f"""
## 축사 현황 (현재 {len(cattle_data)}두)
{cattle_data}
## 사료 단가 (원/kg)
{feed_prices}
## 사용 가능한 사료 목록
{available_feeds}
## 요구사항
1. 일일 사료 비용 최소화
2. 모든 소의 영양 요구량 충족 (TDN 65% 이상, DCP 8% 이상)
3. 사료 전환 시 7일 전환 기간 고려
4. 분기별 사료 가격 변동 예측 포함
아래 JSON 형식으로 응답하세요:
{{
"daily_feed_plan": {{
"morning": {{"feed_type": "...", "amount_kg": 숫자, "cost_won": 숫자}},
"evening": {{"feed_type": "...", "amount_kg": 숫자, "cost_won": 숫자}}
}},
"quarterly_cost_estimate_won": 숫자,
"nutrition_analysis": {{"tdn_percent": 숫자, "dcp_percent": 숫자}},
"price_risk_assessment": "...",
"alternatives": [{{"scenario": "...", "cost_savings_won": 숫자}}]
}}
"""
payload = {
"model": "claude-sonnet-4-20250514",
"messages": [
{"role": "user", "content": user_prompt}
],
"system": system_prompt,
"max_tokens": 2000,
"temperature": 0.4
}
headers = {
"Authorization": f"Bearer {HOLYSHEEP_API_KEY}",
"Content-Type": "application/json",
"anthropic-version": "2023-06-01"
}
start_time = datetime.now()
response = requests.post(
f"{BASE_URL}/messages",
json=payload,
headers=headers,
timeout=30
)
end_time = datetime.now()
latency_ms = (end_time - start_time).total_seconds() * 1000
if response.status_code == 200:
result = response.json()
content = result["content"][0]["text"]
usage = result.get("usage", {})
input_tokens = usage.get("input_tokens", 0)
output_tokens = usage.get("output_tokens", 0)
cost_usd = (input_tokens / 1_000_000 * 15) + (output_tokens / 1_000_000 * 15)
print(f"[성공] 사료 전략 최적화 완료")
print(f"[비용] ${cost_usd:.4f}")
print(f"[지연] {latency_ms:.0f}ms")
return {
"status": "success",
"strategy": content,
"cost_usd": cost_usd,
"latency_ms": latency_ms,
"tokens_used": input_tokens + output_tokens
}
else:
print(f"[오류] {response.status_code}: {response.text}")
return {"status": "error", "message": response.text}
테스트 실행
cattle_data = [
{"id": "S001", "weight_kg": 450, "age_months": 18, "growth_stage": "비육기"},
{"id": "S002", "weight_kg": 380, "age_months": 14, "growth_stage": "비육前期"},
]
feed_prices = {
"조사료A": 850,
"조사료B": 920,
"배합사료A": 1_450,
"배합사료B": 1_380,
"에너지사료": 1_200
}
available_feeds = ["조사료A", "조사료B", "배합사료A", "배합사료B", "에너지사료"]
result = optimize_feed_strategy(cattle_data, feed_prices, available_feeds)
print(result)
3. 다중 모델 Fallback과配额 관리 시스템
"""
HolySheep AI - 다중 모델 Fallback 및 Quota 관리 시스템
주력 모델 장애 시 자동 전환, 비용 할당량 관리
"""
import time
import requests
from enum import Enum
from dataclasses import dataclass
from typing import Optional, Callable
from datetime import datetime, timedelta
HOLYSHEEP_API_KEY = "YOUR_HOLYSHEEP_API_KEY"
BASE_URL = "https://api.holysheep.ai/v1"
class ModelPriority(Enum):
PRIMARY = 1 # Claude Sonnet 4 - $15/MTok
SECONDARY = 2 # Gemini 2.5 Flash - $2.50/MTok
TERTIARY = 3 # DeepSeek V3.2 - $0.42/MTok (비용 최적화)
@dataclass
class ModelConfig:
name: str
api_model: str
cost_per_mtok: float
max_tokens: int
timeout: int
fallback_models: list
@dataclass
class QuotaUsage:
daily_limit_usd: float
daily_used_usd: float
model_limits: dict # 모델별 일일 한도
class HolySheepMultiModelClient:
"""다중 모델 지원 및 자동 fallback 클라이언트"""
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = BASE_URL
# 모델 설정
self.models = {
"claude": ModelConfig(
name="Claude Sonnet 4",
api_model="claude-sonnet-4-20250514",
cost_per_mtok=15.0,
max_tokens=2000,
timeout=30,
fallback_models=["gemini", "deepseek"]
),
"gemini": ModelConfig(
name="Gemini 2.5 Flash",
api_model="gemini-2.5-flash-preview-05-20",
cost_per_mtok=2.50,
max_tokens=1000,
timeout=15,
fallback_models=["deepseek"]
),
"deepseek": ModelConfig(
name="DeepSeek V3.2",
api_model="deepseek-chat-v3.2",
cost_per_mtok=0.42,
max_tokens=1500,
timeout=20,
fallback_models=[]
)
}
# Quota 관리
self.quota = QuotaUsage(
daily_limit_usd=50.0,
daily_used_usd=0.0,
model_limits={
"claude": 20.0, # Claude에 $20 할당
"gemini": 15.0, # Gemini에 $15 할당
"deepseek": 15.0 # DeepSeek에 $15 할당
}
)
self.last_reset = datetime.now()
def _check_quota(self, model_key: str, estimated_cost: float) -> bool:
"""할당량 확인 및 리셋 로직"""
now = datetime.now()
# 일일 리셋
if (now - self.last_reset).days >= 1:
self.quota.daily_used_usd = 0.0
self.last_reset = now
print("[INFO] 일일 할당량 리셋됨")
# 모델별 할당량 확인
remaining = self.quota.model_limits.get(model_key, 0) - estimated_cost
if remaining < 0:
print(f"[경고] {model_key} 모델 할당량 초과, fallback 시도")
return False
return True
def _make_request(self, model_key: str, payload: dict) -> Optional[dict]:
"""단일 모델 API 호출"""
model = self.models[model_key]
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
try:
start = time.time()
response = requests.post(
f"{self.base_url}/chat/completions",
json=payload,
headers=headers,
timeout=model.timeout
)
latency_ms = (time.time() - start) * 1000
if response.status_code == 200:
result = response.json()
usage = result.get("usage", {})
tokens = usage.get("total_tokens", 0)
cost = tokens / 1_000_000 * model.cost_per_mtok
return {
"success": True,
"model_used": model_key,
"data": result,
"latency_ms": latency_ms,
"cost_usd": cost,
"tokens": tokens
}
else:
print(f"[실패] {model.name}: {response.status_code}")
return None
except requests.exceptions.Timeout:
print(f"[타임아웃] {model.name}")
return None
except Exception as e:
print(f"[예외] {model.name}: {str(e)}")
return None
def smart_completion(
self,
model_key: str,
messages: list,
system_prompt: str = ""
) -> dict:
"""
스마트 완성: Quota 확인 → 주력 모델 시도 → Fallback 순회
"""
model = self.models[model_key]
# 1차 시도: 주력 모델
payload = {
"model": model.api_model,
"messages": messages,
"system": system_prompt,
"max_tokens": model.max_tokens
}
result = self._make_request(model_key, payload)
if result and result["success"]:
self.quota.daily_used_usd += result["cost_usd"]
print(f"[성공] {result['model_used']} 사용 (${result['cost_usd']:.4f})")
return result
# 2차 시도: Fallback 모델 순회
for fallback_key in model.fallback_models:
if not self._check_quota(fallback_key, 0.1): # 최소 비용 확인
continue
print(f"[Fallback] {fallback_key} 시도...")
result = self._make_request(fallback_key, payload)
if result and result["success"]:
self.quota.daily_used_usd += result["cost_usd"]
print(f"[Fallback 성공] {result['model_used']} 사용")
return result
return {
"success": False,
"error": "모든 모델 실패",
"model_tried": [model_key] + model.fallback_models
}
def get_usage_report(self) -> dict:
"""사용량 리포트 반환"""
return {
"daily_used_usd": self.quota.daily_used_usd,
"daily_limit_usd": self.quota.daily_limit_usd,
"remaining_usd": self.quota.daily_limit_usd - self.quota.daily_used_usd,
"model_usage": self.quota.model_limits
}
사용 예시
if __name__ == "__main__":
client = HolySheepMultiModelClient(HOLYSHEEP_API_KEY)
# 사료 관련 질문
messages = [
{"role": "user", "content": "비육기 한우의 최적 사료 전환 시기는 언제인가요?"}
]
result = client.smart_completion(
model_key="claude",
messages=messages,
system_prompt="당신은 축산 전문가입니다."
)
print(f"\n결과: {result}")
print(f"\n사용량 리포트: {client.get_usage_report()}")
실제 성능 측정 결과
2026년 4월 1일부터 5월 25일까지 약 8주간 프로덕션 환경에서 측정한 실제 성능 데이터입니다.
| 지표 | Gemini 2.5 Flash | Claude Sonnet 4 | DeepSeek V3.2 |
|---|---|---|---|
| 평균 응답 시간 | 820ms | 1,450ms | 650ms |
| 성공률 | 99.2% | 98.7% | 99.8% |
| P95 지연 시간 | 1,200ms | 2,100ms | 950ms |
| 월간 사용량 | 450만 토큰 | 120만 토큰 | 800만 토큰 |
| 월간 비용 | $11.25 | $18.00 | $3.36 |
| 최대 연속 실패 | 2회 (네트워크) | 0회 | 0회 |
| Fallback 전환 횟수 | 8회 | 15회 | 0회 |
이런 팀에 적합 / 비적합
적합한 팀
- 국내 스마트팜 / AgriTech 스타트업: 해외 신용카드 없이 AI API를 도입하고 싶은 팀. HolySheep의 로컬 결제 지원이 필수적입니다.
- 다중 AI 모델을 활용하는 프로젝트: 체중 추정, 영상 분석, 자연어 생성 등 서로 다른 태스크에 최적화된 모델을 한 곳에서 관리하고 싶은 경우.
- 비용 최적화가 중요한 프로젝트: DeepSeek V3.2의 $0.42/MTok 가격优势和 Gemini 2.5 Flash의 빠른 응답 속도를 활용한 하이브리드 아키텍처를 구축하려는 팀.
- 신속한 프로토타이핑이 필요한 팀: 무료 크레딧으로 즉시 테스트를 시작하고 싶거나, 여러 모델의 성능을 빠르게 비교検証하려는 경우.
- 장애 대응 자동화가 필요한 팀: 단일 모델 의존도를 낮추고 자동으로 Fallback하는 안정적인 파이프라인이 필요한 경우.
비적합한 팀
- 대규모 Enterprise 사용: 월 10억 토큰 이상 사용하는 경우, 직접 API 연동이나 전용 인스턴스가 더 비용 효율적일 수 있습니다.
- 극단적 저지연이 필요한 경우: 실시간 트레이딩이나 밀리초 단위 반응이 필요한 시스템에서는 응답 시간 오버헤드가 감안이 필요합니다.
- 특정 모델만 고수하려는 팀: 단일 모델만 사용하고 Gateway 비용을 감수할 이유가 없는 경우.
가격과 ROI
우리 팀의 실제 비용 구조를 분석한 결과입니다.
| 항목 | HolySheep AI | 직접 API 연동 (비교) | 절감 효과 |
|---|---|---|---|
| 월간 API 비용 | $32.61 | $38.50 | $5.89 (15.3% 절감) |
| 결제 수수료 | $0 (로컬 결제) | $3.50 (해외 카드) | $3.50 |
| 개발 시간 절약 | ~40시간/월 | 수동 관리 | 고용 비용 절약 효과 |
| 장애 대응 시간 | 0 (자동 Fallback) | ~2시간/회 | 월 $200+ 시간 비용 |
| 총 월간 ROI | 약 $250+ 절감 + 안정성 향상 | ||
특히 로컬 결제 지원으로 해외 신용카드 수수료 $3.50이 사라졌고, 자동 Fallback 시스템으로 월평균 2회 발생하던 서비스 장애 시 복구 시간이 0으로 줄었습니다. 장애 1회당 약 2시간 소요 × 월 2회 × 시급 $50 = 월 $200 인건비 절약 효과가 있었습니다.
콘솔 UX 평가
HolySheep 콘솔은 국내 개발자 관점에서 상당히 직관적으로 설계되어 있습니다.
- 대시보드: 사용량 그래프가 실시간으로 업데이트되어 일별, 모델별 비용을 한눈에 파악할 수 있습니다.
- API 키 관리: 여러 API 키 발급 및 라벨링이 가능하여 개발/스테이징/프로덕션 환경을 분리 관리할 수 있습니다.
- 사용량 알림: 일일 또는 월간 임계치 설정 시 이메일을 통해 알림을 받을 수 있어 비용 초과를 방지할 수 있습니다.
- 로그 확인: API 호출 로그를 상세히 확인할 수 있어 문제 발생 시 빠른 디버깅이 가능합니다.
자주 발생하는 오류와 해결
실제 개발 과정에서 겪은 오류들과 해결 방법을 정리합니다.
오류 1: 401 Unauthorized - 잘못된 API 키
# 오류 메시지
{"error": {"message": "Invalid authentication", "type": "invalid_request_error"}}
원인: API 키가 만료되었거나 잘못된 형식
해결: HolySheep 콘솔에서 새로운 API 키 발급
import os
HOLYSHEEP_API_KEY = os.environ.get("HOLYSHEEP_API_KEY", "YOUR_HOLYSHEEP_API_KEY")
키 유효성 검사
if not HOLYSHEEP_API_KEY or HOLYSHEEP_API_KEY == "YOUR_HOLYSHEEP_API_KEY":
raise ValueError("""
HolySheep API 키가 설정되지 않았습니다.
1. https://www.holysheep.ai/console 에 접속
2. API Keys 메뉴에서 새 키 발급
3. 환경 변수로 HOLYSHEEP_API_KEY 설정
""")
오류 2: 429 Rate Limit 초과
# 오류 메시지
{"error": {"message": "Rate limit exceeded", "type": "rate_limit_error"}}
해결: HolySheepMultiModelClient의 fallback 메커니즘 활용
또는 지수 백오프(Exponential Backoff) 구현
import time
import random
def request_with_retry(func, max_retries=3, base_delay=1):
"""지수 백오프와 함께 요청 재시도"""
for attempt in range(max_retries):
try:
result = func()
if result and result.get("success"):
return result
except Exception as e:
pass
if attempt < max_retries - 1:
delay = base_delay * (2 ** attempt) + random.uniform(0, 1)
print(f"[재시도] {delay:.1f}초 후 재시도 ({attempt + 1}/{max_retries})")
time.sleep(delay)
return {"success": False, "error": "최대 재시도 횟수 초과"}
사용 예시
result = request_with_retry(
lambda: client.smart_completion("claude", messages)
)
오류 3: 모델 특정 응답 형식 불일치
# 오류 메시지
Claude는 Anthropic 형식, OpenAI 호환 형식 혼용 문제
해결: HolySheep의 универсальный 클라이언트 추상화
class UniversalModelClient:
"""모든 모델을统一된 인터페이스로 호출"""
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.holysheep.ai/v1"
def call(self, model: str, prompt: str, **kwargs) -> dict:
# Claude 모델 체크
if "claude" in model:
return self._call_claude(prompt, model, **kwargs)
else:
# OpenAI 호환 형식 (Gemini, DeepSeek 등)
return self._call_openai_compat(model, prompt, **kwargs)
def _call_claude(self, prompt: str, model: str, **kwargs) -> dict:
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",
"anthropic-version": "2023-06-01"
}
payload = {
"model": model,
"messages": [{"role": "user", "content": prompt}],
"max_tokens": kwargs.get("max_tokens", 1000)
}
response = requests.post(
f"{self.base_url}/messages",
json=payload,
headers=headers,
timeout=kwargs.get("timeout", 30)
)
return response.json()
def _call_openai_compat(self, model: str, prompt: str, **kwargs) -> dict:
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
payload = {
"model": model,
"messages": [{"role": "user", "content": prompt}],
"max_tokens": kwargs.get("max_tokens", 1000)
}
response = requests.post(
f"{self.base_url}/chat/completions",
json=payload,
headers=headers,
timeout=kwargs.get("timeout", 15)
)
return response.json()
사용: 모델명만 지정하면 알아서 처리
client = UniversalModelClient(HOLYSHEEP_API_KEY)
result1 = client.call("claude-sonnet-4-20250514", "한우 사료 추천")
result2 = client.call("gemini-2.5-flash-preview-05-20", "소 체중 추정")
오류 4: 이미지 인코딩 실패
# 오류 메시지
{"error": {"message": "Invalid image format", ...}}
해결: Pillow로 이미지 전처리 후 올바른 형식으로 인코딩
from PIL import Image
import base64
from io import BytesIO
def prepare_image_for_api(image_path: str, max_size_kb: int = 4000) -> str:
"""
이미지를 HolySheep API 호환 형식으로 전처리
- JPEG/PNG/WebP → JPEG 변환
- 크기 제한 (대부분의 API는 5-20MB 제한)
- base64 인코딩
"""
with Image.open(image_path) as img:
# RGBA → RGB 변환 (JPEG는 알파 채널 미지원)
if img.mode in ("RGBA", "LA", "P"):
background = Image.new("RGB", img.size, (255, 255, 255))
if img.mode == "P":
img = img.convert("RGBA")
background.paste(img, mask=img.split()[-1] if img.mode == "RGBA" else None)
img = background
# 크기 최적화
output = BytesIO()
quality = 85
img.save(output, format="JPEG", quality=quality, optimize=True)
while output.tell() > max_size_kb * 1024 and quality > 50:
output = BytesIO()
quality -= 5
img.save(output, format="JPEG", quality=quality, optimize=True)
return base64.b64encode(output.getvalue()).decode("utf-8")
사용