Nano Banana Pro API를 호출하여 이미지를 생성할 때, 동기 호출과 비동기 호출은 어떤 차이가 있을까요? 현재 APIYI와 Gemini 공식 플랫폼은 모두 동기 호출 모드만을 지원하고 있지만, APIYI는 OSS URL 이미지 출력 방식을 제공하여 사용자 경험을 획기적으로 개선했습니다. 본 글에서는 동기 호출과 비동기 호출의 핵심적인 차이점을 체계적으로 분석하고, 이미지 출력 형식에 대한 APIYI 플랫폼의 최적화 솔루션을 살펴봅니다.
핵심 가치: 이 글을 통해 API 설계에서 동기 호출과 비동기 호출의 본질적인 차이, base64 인코딩 대비 APIYI 플랫폼의 OSS URL 출력 방식이 갖는 장점, 그리고 비즈니스 시나리오에 맞는 최적의 이미지 획득 방안을 이해하게 될 것입니다.

Nano Banana Pro API 호출 모드 핵심 비교
| 특성 | 동기 호출 (Synchronous) | 비동기 호출 (Asynchronous) | APIYI 현재 지원 |
|---|---|---|---|
| 연결 모드 | HTTP 연결 유지, 완료 대기 | 작업 ID 즉시 반환 후 연결 종료 | ✅ 동기 호출 |
| 대기 방식 | 블로킹 대기 (30-170초) | 논블로킹, 폴링 또는 Webhook | ✅ 동기 (블로킹 대기) |
| 타임아웃 위험 | 높음 (300-600초 설정 필요) | 낮음 (작업 제출에만 짧은 타임아웃 필요) | ⚠️ 적절한 타임아웃 설정 권장 |
| 구현 복잡도 | 낮음 (단일 요청으로 완료) | 중간 (폴링 또는 Webhook 리스너 필요) | ✅ 간단하고 사용하기 쉬움 |
| 적용 시나리오 | 실시간 생성, 즉시 표시 | 일괄 처리, 백그라운드 작업 | ✅ 실시간 생성 |
| 비용 최적화 | 표준 가격 | Google Batch API 활용 시 50% 절감 가능 | – |
동기 호출의 작동 원리
**동기 호출 (Synchronous Call)**은 요청-대기-응답 패턴을 따릅니다.
- 클라이언트 요청 시작: 서버에 이미지 생성 요청을 보냅니다.
- HTTP 연결 유지: 클라이언트는 TCP 연결을 열어둔 상태로 서버의 추론이 끝나기를 기다립니다.
- 블로킹 대기: 30~170초의 추론 시간 동안 클라이언트는 다른 작업을 처리할 수 없습니다.
- 전체 응답 수신: 서버가 생성된 이미지 데이터(base64 또는 URL)를 반환합니다.
- 연결 종료: 작업 완료 후 HTTP 연결을 닫습니다.
주요 특징: 동기 호출은 블로킹(Blocking) 방식입니다. 클라이언트는 서버 응답을 받을 때까지 후속 작업을 진행할 수 없습니다. 따라서 추론이 완료되기 전에 연결이 끊어지지 않도록 충분한 타임아웃 시간(1K/2K는 300초, 4K는 600초 권장)을 설정해야 합니다.
비동기 호출의 작동 원리
**비동기 호출 (Asynchronous Call)**은 요청-수락-통지 패턴을 따릅니다.
- 클라이언트 작업 제출: 서버에 이미지 생성 요청을 보냅니다.
- 작업 ID 즉시 반환: 서버는 요청을 수락하고 작업 ID(예:
task_abc123)를 반환한 뒤 즉시 연결을 닫습니다. - 백그라운드 추론: 서버가 백그라운드에서 이미지를 생성하는 동안 클라이언트는 다른 작업을 수행할 수 있습니다.
- 결과 획득: 클라이언트는 다음 두 가지 방식 중 하나로 결과를 가져옵니다.
- 폴링 (Polling): 정기적으로
/tasks/task_abc123/status에 요청을 보내 작업 상태를 확인합니다. - Webhook 콜백: 작업이 완료되면 서버가 클라이언트가 제공한 콜백 URL을 호출합니다.
- 폴링 (Polling): 정기적으로
- 이미지 다운로드: 작업 완료 후 반환된 URL을 통해 생성된 이미지를 다운로드합니다.
주요 특징: 비동기 호출은 논블로킹(Non-blocking) 방식입니다. 클라이언트는 작업을 제출한 후 즉시 다른 요청을 처리할 수 있으며, 연결을 오래 유지할 필요가 없습니다. 일괄 처리, 백그라운드 작업 및 실시간성이 아주 중요하지 않은 시나리오에 적합합니다.
💡 기술 제안: APIYI 플랫폼은 현재 동기 호출 모드만 지원하지만, 타임아웃 설정을 최적화하고 OSS URL 출력을 제공함으로써 사용자 경험을 크게 향상시켰습니다. 대량의 이미지를 생성해야 하는 경우, APIYI(apiyi.com) 플랫폼을 통해 호출하는 것을 추천합니다. 이 플랫폼은 안정적인 HTTP 포트 인터페이스를 제공하며, 합리적인 타임아웃이 기본 설정되어 있어 고성능 동기 호출을 지원합니다.

핵심 차이 1: 연결 유지 시간 및 타임아웃 설정
동기 호출의 연결 유지 요구 사항
동기 호출은 클라이언트가 전체 이미지 생성 과정 동안 HTTP 연결을 열린 상태로 유지해야 합니다. 이로 인해 다음과 같은 기술적 과제가 발생해요.
| 과제 | 영향 | 해결 방법 |
|---|---|---|
| 장시간 유휴 연결 | 중간 네트워크 장비(NAT, 방화벽)가 연결을 끊을 수 있음 | TCP Keep-Alive 설정 |
| 타임아웃 설정의 복잡성 | 해상도에 따라 정확한 타임아웃 설정이 필요함 | 1K/2K: 300초, 4K: 600초 |
| 네트워크 불안정에 민감함 | 네트워크 환경이 좋지 않으면 연결이 끊기기 쉬움 | 재시도 메커니즘 구현 |
| 동시 연결 제한 | 브라우저는 기본적으로 최대 6개의 동시 연결만 허용함 | 서버 측 호출을 사용하거나 연결 풀(Connection Pool) 확장 |
Python 동기 호출 예시:
import requests
import time
def generate_image_sync(prompt: str, size: str = "4096x4096") -> dict:
"""
Nano Banana Pro API를 동기 방식으로 호출하여 이미지를 생성합니다.
Args:
prompt: 이미지 프롬프트
size: 이미지 크기
Returns:
API 응답 결과
"""
start_time = time.time()
# 동기 호출: 생성이 완료될 때까지 연결을 유지합니다.
response = requests.post(
"http://api.apiyi.com:16888/v1/images/generations",
json={
"prompt": prompt,
"size": size,
"model": "nano-banana-pro",
"n": 1,
"response_format": "url" # APIYI는 URL 출력을 지원합니다.
},
headers={"Authorization": "Bearer YOUR_API_KEY"},
timeout=(10, 600) # 연결 타임아웃 10초, 읽기 타임아웃 600초
)
elapsed = time.time() - start_time
print(f"⏱️ 동기 호출 소요 시간: {elapsed:.2f}초")
print(f"🔗 연결 상태: {elapsed:.2f}초 동안 열림 유지")
return response.json()
# 사용 예시
result = generate_image_sync(
prompt="A futuristic cityscape at sunset",
size="4096x4096"
)
print(f"✅ 이미지 URL: {result['data'][0]['url']}")
주요 관찰 사항:
- 클라이언트는 100~170초의 추론 시간 동안 완전히 블로킹(대기)됩니다.
- HTTP 연결이 지속적으로 열려 있어 시스템 리소스를 소모합니다.
- 타임아웃 설정이 부적절할 경우(예: 60초), 추론이 끝나기도 전에 연결이 끊어질 수 있습니다.
비동기 호출의 짧은 연결 장점
비동기 호출은 작업 제출 및 상태 조회 시에만 짧게 연결을 맺으므로, 연결 유지 시간을 획기적으로 줄여줍니다.
| 단계 | 연결 시간 | 타임아웃 설정 |
|---|---|---|
| 작업 제출 | 1~3초 | 30초면 충분 |
| 상태 폴링 | 회당 1~2초 | 10초면 충분 |
| 이미지 다운로드 | 5~10초 | 60초면 충분 |
| 합계 | 10~20초 (분산됨) | 동기 호출보다 훨씬 짧음 |
Python 비동기 호출 예시 (향후 APIYI 지원 가상 모델):
import requests
import time
def generate_image_async(prompt: str, size: str = "4096x4096") -> str:
"""
Nano Banana Pro API를 비동기 방식으로 호출하여 이미지를 생성합니다 (향후 기능).
Args:
prompt: 이미지 프롬프트
size: 이미지 크기
Returns:
작업 ID
"""
# 1단계: 작업 제출 (짧은 연결)
response = requests.post(
"http://api.apiyi.com:16888/v1/images/generations/async", # 향후 인터페이스
json={
"prompt": prompt,
"size": size,
"model": "nano-banana-pro",
"n": 1,
"response_format": "url"
},
headers={"Authorization": "Bearer YOUR_API_KEY"},
timeout=(10, 30) # 작업 제출은 30초 타임아웃으로 충분
)
task_data = response.json()
task_id = task_data["task_id"]
print(f"✅ 작업이 제출되었습니다: {task_id}")
print(f"🔓 연결이 닫혔습니다. 이제 다른 작업을 처리할 수 있습니다.")
return task_id
def poll_task_status(task_id: str, max_wait: int = 300) -> dict:
"""
작업이 완료될 때까지 상태를 폴링합니다.
Args:
task_id: 작업 ID
max_wait: 최대 대기 시간 (초)
Returns:
생성 결과
"""
start_time = time.time()
poll_interval = 5 # 5초마다 한 번씩 폴링
while time.time() - start_time < max_wait:
# 작업 상태 조회 (짧은 연결)
response = requests.get(
f"http://api.apiyi.com:16888/v1/tasks/{task_id}", # 향후 인터페이스
headers={"Authorization": "Bearer YOUR_API_KEY"},
timeout=(10, 10) # 상태 조회는 10초 타임아웃으로 충분
)
status_data = response.json()
status = status_data["status"]
if status == "completed":
elapsed = time.time() - start_time
print(f"✅ 작업 완료! 총 소요 시간: {elapsed:.2f}초")
return status_data["result"]
elif status == "failed":
raise Exception(f"작업 실패: {status_data.get('error')}")
else:
print(f"⏳ 작업 상태: {status}, {poll_interval}초 후 다시 시도합니다...")
time.sleep(poll_interval)
raise TimeoutError(f"작업 시간 초과: {task_id}")
# 사용 예시
task_id = generate_image_async(
prompt="A serene mountain landscape",
size="4096x4096"
)
# 폴링하는 동안 다른 작업을 병렬로 처리할 수 있습니다.
print("🚀 다른 요청을 동시에 처리하는 중...")
# 작업 상태 폴링
result = poll_task_status(task_id, max_wait=600)
print(f"✅ 이미지 URL: {result['data'][0]['url']}")
Webhook 콜백 모드 예시 보기 (향후 기능)
from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
# 작업 결과를 저장할 전역 딕셔너리
task_results = {}
@app.route('/webhook/image_completed', methods=['POST'])
def handle_webhook():
"""APIYI 비동기 작업 완료 시 Webhook 콜백을 수신합니다."""
data = request.json
task_id = data['task_id']
status = data['status']
result = data.get('result')
if status == 'completed':
task_results[task_id] = result
print(f"✅ 작업 {task_id} 완료: {result['data'][0]['url']}")
else:
print(f"❌ 작업 {task_id} 실패: {data.get('error')}")
return jsonify({"received": True}), 200
def generate_image_with_webhook(prompt: str, size: str = "4096x4096") -> str:
"""
Webhook 모드를 사용하여 비동기로 이미지를 생성합니다.
Args:
prompt: 이미지 프롬프트
size: 이미지 크기
Returns:
작업 ID
"""
response = requests.post(
"http://api.apiyi.com:16888/v1/images/generations/async",
json={
"prompt": prompt,
"size": size,
"model": "nano-banana-pro",
"n": 1,
"response_format": "url",
"webhook_url": "https://your-domain.com/webhook/image_completed" # 콜백 URL
},
headers={"Authorization": "Bearer YOUR_API_KEY"},
timeout=(10, 30)
)
task_id = response.json()["task_id"]
print(f"✅ 작업이 제출되었습니다: {task_id}")
print(f"📞 Webhook 콜백 예정 주소: https://your-domain.com/webhook/image_completed")
return task_id
# Webhook 리스닝을 위한 Flask 서버 실행
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
🎯 현재 제한 사항: 현재 APIYI와 Gemini 공식 API는 모두 동기 호출 모드만 지원하며, 비동기 호출 기능은 향후 버전에서 출시될 예정입니다. 높은 동시성이 필요한 이미지 생성 시나리오에서는 APIYI(apiyi.com) 플랫폼을 통해 멀티스레딩 또는 멀티프로세싱을 활용하여 동기 인터페이스를 병렬로 호출하고, 합리적인 타임아웃을 설정하는 것을 권장합니다.
핵심 차이 2: 동시 처리 능력 및 리소스 점유
동기 호출의 동시성 제한
동기 호출은 대규모 동시 처리 시나리오에서 상당한 리소스 점유 문제를 겪게 됩니다.
단일 스레드 블로킹 문제:
import time
# ❌ 잘못된 예: 단일 스레드 순차 호출, 총 소요 시간 = 단일 실행 시간 × 작업 수
def generate_multiple_images_sequential(prompts: list) -> list:
results = []
start_time = time.time()
for prompt in prompts:
result = generate_image_sync(prompt, size="4096x4096")
results.append(result)
elapsed = time.time() - start_time
print(f"❌ 순차 호출로 {len(prompts)}장의 이미지를 생성하는 데 소요된 시간: {elapsed:.2f}초")
# 이미지당 120초라고 가정하면, 10장의 경우 = 1200초 (20분!)
return results
멀티스레드 동시성 최적화:
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
# ✅ 올바른 예: 멀티스레드 병렬 호출로 I/O 대기 시간을 충분히 활용
def generate_multiple_images_concurrent(prompts: list, max_workers: int = 5) -> list:
"""
멀티스레드를 사용하여 여러 장의 이미지를 동시에 생성합니다.
Args:
prompts: 프롬프트 리스트
max_workers: 최대 동시 작업 스레드 수
Returns:
생성 결과 리스트
"""
results = []
start_time = time.time()
with ThreadPoolExecutor(max_workers=max_workers) as executor:
# 모든 작업 제출
future_to_prompt = {
executor.submit(generate_image_sync, prompt, "4096x4096"): prompt
for prompt in prompts
}
# 모든 작업 완료 대기
for future in as_completed(future_to_prompt):
prompt = future_to_prompt[future]
try:
result = future.result()
results.append(result)
print(f"✅ 완료: {prompt[:30]}...")
except Exception as e:
print(f"❌ 실패: {prompt[:30]}... - {e}")
elapsed = time.time() - start_time
print(f"✅ 병렬 호출로 {len(prompts)}장의 이미지를 생성하는 데 소요된 시간: {elapsed:.2f}초")
# 이미지당 120초라고 가정하면, 10장의 경우 ≈ 120-150초 (2~2.5분)
return results
# 사용 예시
prompts = [
"A cyberpunk city at night",
"A serene forest landscape",
"An abstract geometric pattern",
"A futuristic space station",
"A vintage car in the desert",
# ...더 많은 프롬프트
]
results = generate_multiple_images_concurrent(prompts, max_workers=5)
print(f"🎉 총 {len(results)}장의 이미지가 생성되었습니다.")
| 동시성 방식 | 4K 이미지 10장 소요 시간 | 리소스 점유 | 적용 시나리오 |
|---|---|---|---|
| 순차 호출 | 1200초 (20분) | 낮음 (단일 연결) | 단일 이미지, 실시간 생성 |
| 멀티스레드 병렬 (5 스레드) | 250초 (4분) | 중간 (5개 연결) | 중소규모 배치 (10~50장) |
| 멀티프로세스 병렬 (10 프로세스) | 150초 (2.5분) | 높음 (10개 연결) | 대규모 배치 (50장 이상) |
| 비동기 호출 (향후) | 120초 + 폴링 오버헤드 | 낮음 (짧은 폴링 연결) | 초대규모 배치 (100장 이상) |
비동기 호출의 동시성 장점
비동기 호출은 배치 처리 시나리오에서 독보적인 우위를 점합니다.
배치 제출 + 배치 폴링:
def generate_batch_async(prompts: list) -> list:
"""
배치 비동기 이미지 생성 (향후 기능)
Args:
prompts: 프롬프트 리스트
Returns:
작업 ID 리스트
"""
task_ids = []
# 1단계: 모든 작업을 빠르게 배치로 제출 (각 1~3초 소요)
for prompt in prompts:
task_id = generate_image_async(prompt, size="4096x4096")
task_ids.append(task_id)
print(f"✅ {len(task_ids)}개 작업 배치 제출 완료, 소요 시간 약 {len(prompts) * 2}초")
# 2단계: 작업 상태 배치 폴링
results = []
for task_id in task_ids:
result = poll_task_status(task_id, max_wait=600)
results.append(result)
return results
| 지표 | 동기 호출 (멀티스레드) | 비동기 호출 (향후) | 차이점 |
|---|---|---|---|
| 제출 단계 소요 시간 | 1200초 (블로킹 대기) | 20초 (빠른 제출) | 비동기가 60배 빠름 |
| 총 소요 시간 | 250초 (5 스레드) | 120초 + 폴링 오버헤드 | 비동기가 2배 빠름 |
| 피크 연결 수 | 5개 긴 연결 | 1개 짧은 연결 (제출 시) | 비동기가 연결 80% 절약 |
| 기타 작업 처리 가능 여부 | ❌ 스레드 블로킹 | ✅ 완전 비블로킹 | 비동기가 더 유연함 |

💰 비용 최적화: Google Gemini API는 Batch API 모드를 제공하여 비동기 처리를 지원하며, 50%의 가격 할인 혜택을 줍니다(표준 가격 장당 $0.133-$0.24, Batch API 장당 $0.067-$0.12). 단, 최대 24시간의 처리 시간을 감수해야 합니다. 실시간 생성이 필요 없는 시나리오라면 Batch API를 사용하여 비용을 절감해 보세요.
핵심 차이점 3: APIYI 플랫폼의 OSS URL 출력 장점
base64 인코딩 vs URL 출력 비교
Nano Banana Pro API는 두 가지 이미지 출력 형식을 지원해요.
| 특성 | base64 인코딩 | OSS URL 출력 (APIYI 독점) | 권장 여부 |
|---|---|---|---|
| 응답 본문 크기 | 6-8 MB (4K 이미지) | 200 바이트 (URL만 포함) | URL ✅ |
| 전송 시간 | 5-10 초 (네트워크가 불안정하면 더 느려짐) | < 1 초 | URL ✅ |
| 브라우저 캐시 | ❌ 캐싱 불가 | ✅ 표준 HTTP 캐시 지원 | URL ✅ |
| CDN 가속 | ❌ 사용 불가 | ✅ 글로벌 CDN 가속 지원 | URL ✅ |
| 이미지 최적화 | ❌ WebP 등 미지원 | ✅ 포맷 변환 지원 | URL ✅ |
| 점진적 로딩 | ❌ 전체 다운로드 필수 | ✅ 점진적 로딩(Progressive Loading) 지원 | URL ✅ |
| 모바일 성능 | ❌ 메모리 점유율 높음 | ✅ 최적화된 다운로드 스트림 | URL ✅ |
base64 인코딩의 성능 문제:
-
응답 본문 33% 비대화: base64 인코딩을 하면 데이터 양이 약 33% 정도 늘어나요.
- 원본 4K 이미지: 약 6 MB
- base64 인코딩 후: 약 8 MB
-
CDN 활용 불가: base64 문자열이 JSON 응답에 포함되어 있어 CDN을 통한 캐싱이 불가능해요.
-
모바일 기기 메모리 부하: base64 문자열을 디코딩하려면 추가적인 메모리와 CPU 자원이 소모돼요.
APIYI OSS URL 출력의 장점:
import requests
# ✅ 권장: APIYI OSS URL 출력 사용
response = requests.post(
"http://api.apiyi.com:16888/v1/images/generations",
json={
"prompt": "A beautiful sunset over mountains",
"size": "4096x4096",
"model": "nano-banana-pro",
"n": 1,
"response_format": "url" # URL 출력 지정
},
headers={"Authorization": "Bearer YOUR_API_KEY"},
timeout=(10, 600)
)
result = response.json()
# 응답 본문에는 URL만 포함되며, 크기는 약 200바이트입니다.
print(f"응답 본문 크기: {len(response.content)} 바이트")
# 출력: 응답 본문 크기: 234 바이트
# OSS URL 예시
image_url = result['data'][0]['url']
print(f"이미지 URL: {image_url}")
# 출력: https://apiyi-oss.oss-cn-beijing.aliyuncs.com/nano-banana/abc123.png
# 이후 표준 HTTP를 통해 이미지를 다운로드하며, CDN 가속 혜택을 누릴 수 있습니다.
image_response = requests.get(image_url)
with open("output.png", "wb") as f:
f.write(image_response.content)
비교: base64 출력의 성능 문제:
# ❌ 비권장: base64 인코딩 출력
response = requests.post(
"https://api.example.com/v1/images/generations",
json={
"prompt": "A beautiful sunset over mountains",
"size": "4096x4096",
"model": "nano-banana-pro",
"n": 1,
"response_format": "b64_json" # base64 인코딩
},
headers={"Authorization": "Bearer YOUR_API_KEY"},
timeout=(10, 600)
)
result = response.json()
# 응답 본문에 전체 base64 문자열이 포함되어 크기가 약 8MB에 달합니다.
print(f"응답 본문 크기: {len(response.content)} 바이트")
# 출력: 응답 본문 크기: 8388608 바이트 (8 MB!)
# base64 문자열 디코딩이 필요합니다.
import base64
image_b64 = result['data'][0]['b64_json']
image_bytes = base64.b64decode(image_b64)
with open("output.png", "wb") as f:
f.write(image_bytes)
| 비교 지표 | base64 인코딩 | APIYI OSS URL | 성능 향상 |
|---|---|---|---|
| API 응답 크기 | 8 MB | 200 바이트 | 99.998% 감소 |
| API 응답 시간 | 125초 + 5~10초 전송 | 125초 + < 1초 전송 | 5~10초 절약 |
| 이미지 다운로드 방식 | JSON 내 포함 | 독립적인 HTTP 요청 | 병렬 다운로드 가능 |
| 브라우저 캐시 | 캐싱 불가 | 표준 HTTP 캐시 | 재방문 시 즉시 로딩 |
| CDN 가속 | 미지원 | 글로벌 CDN 노드 | 국가 간 접속 가속 |
🚀 권장 설정: APIYI 플랫폼의 Nano Banana Pro API를 호출할 때는 base64 인코딩 대신 항상
response_format: "url"을 사용하여 OSS URL 출력을 받으세요. 이는 API 응답 크기와 전송 시간을 획기적으로 줄여줄 뿐만 아니라, CDN 가속과 브라우저 캐시를 십분 활용하여 사용자 경험을 크게 높여줍니다.
핵심 차이점 4: 활용 사례 및 향후 계획
동기 호출의 최적 활용 사례
추천 시나리오:
- 실시간 이미지 생성: 사용자가 프롬프트를 제출한 후 즉시 생성된 이미지를 보여줘야 할 때
- 소규모 배치 처리: 1~10장의 이미지를 생성할 때 병렬 호출만으로도 성능 요구사항을 충족할 수 있는 경우
- 간편한 연동: 폴링(Polling)이나 웹훅(Webhook)을 구현할 필요가 없어 개발 복잡도가 낮음
- 대화형 애플리케이션: AI 드로잉 툴, 이미지 에디터 등 즉각적인 피드백이 필요한 서비스
전형적인 코드 패턴:
from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
@app.route('/generate', methods=['POST'])
def generate_image():
"""실시간 이미지 생성 인터페이스"""
data = request.json
prompt = data['prompt']
size = data.get('size', '1024x1024')
# 동기 호출, 사용자는 생성이 완료될 때까지 대기
response = requests.post(
"http://api.apiyi.com:16888/v1/images/generations",
json={
"prompt": prompt,
"size": size,
"model": "nano-banana-pro",
"n": 1,
"response_format": "url"
},
headers={"Authorization": "Bearer YOUR_API_KEY"},
timeout=(10, 300 if size != '4096x4096' else 600)
)
result = response.json()
return jsonify({
"success": True,
"image_url": result['data'][0]['url']
})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
비동기 호출의 향후 활용 사례
활용 사례 (향후 지원 예정):
- 대량 이미지 생성: 이커머스 상품 이미지 일괄 생성, 디자인 에셋 라이브러리 구축 등 100장 이상의 이미지를 생성할 때
- 백그라운드 예약 작업: 매일 특정 유형의 이미지를 자동 생성하며 실시간 응답이 필요 없는 경우
- 저비용 처리: Google Batch API를 사용하여 50% 가격 할인을 받고, 24시간 이내의 인도 시간을 허용할 때
- 고동시성(High Concurrency) 시나리오: 수백 명의 사용자가 동시에 생성 요청을 제출하여 커넥션 풀 고갈을 방지해야 할 때
전형적인 코드 패턴 (향후 예시):
from flask import Flask, request, jsonify
from celery import Celery
import requests
app = Flask(__name__)
celery = Celery('tasks', broker='redis://localhost:6379/0')
@celery.task
def generate_image_task(prompt: str, size: str, user_id: str):
"""Celery 비동기 작업: 이미지 생성"""
# APIYI에 비동기 작업 제출
response = requests.post(
"http://api.apiyi.com:16888/v1/images/generations/async", # 향후 추가될 인터페이스
json={
"prompt": prompt,
"size": size,
"model": "nano-banana-pro",
"n": 1,
"response_format": "url",
"webhook_url": f"https://your-domain.com/webhook/{user_id}"
},
headers={"Authorization": "Bearer YOUR_API_KEY"},
timeout=(10, 30)
)
task_id = response.json()["task_id"]
return task_id
@app.route('/generate_async', methods=['POST'])
def generate_image_async():
"""비동기 이미지 생성 인터페이스"""
data = request.json
prompt = data['prompt']
size = data.get('size', '1024x1024')
user_id = data['user_id']
# Celery 작업 제출 후 즉시 반환
task = generate_image_task.delay(prompt, size, user_id)
return jsonify({
"success": True,
"message": "작업이 제출되었습니다. 완료되면 웹훅을 통해 알려드릴게요.",
"task_id": task.id
})
@app.route('/webhook/<user_id>', methods=['POST'])
def handle_webhook(user_id: str):
"""APIYI 비동기 작업 완료 웹훅 콜백 수신"""
data = request.json
task_id = data['task_id']
result = data['result']
# 사용자에게 이미지 생성 완료 알림 (메일 발송, 푸시 알림 등)
notify_user(user_id, result['data'][0]['url'])
return jsonify({"received": True}), 200
APIYI 플랫폼의 향후 계획
| 기능 | 현재 상태 | 향후 계획 | 예상 시기 |
|---|---|---|---|
| 동기 호출 | ✅ 지원 중 | 타임아웃 설정 지속적 최적화 | – |
| OSS URL 출력 | ✅ 지원 중 | CDN 노드 추가 확충 | 2026 Q2 |
| 비동기 호출 (폴링) | ❌ 미지원 | 작업 제출 및 상태 조회 지원 | 2026 Q2 |
| 비동기 호출 (웹훅) | ❌ 미지원 | 작업 완료 콜백 알림 지원 | 2026 Q2 |
| Batch API 연동 | ❌ 미지원 | Google Batch API 연동 | 2026 Q4 |
💡 개발 팁: APIYI는 2026년 3분기에 작업 제출, 상태 조회 및 웹훅 콜백을 지원하는 비동기 호출 기능을 출시할 계획이에요. 현재 대량 처리가 필요한 개발자분들은 동기 인터페이스를 멀티스레드로 병렬 호출하시고, APIYI(apiyi.com) 플랫폼을 통해 안정적인 HTTP 포트 인터페이스와 최적화된 타임아웃 설정을 활용해 보시길 추천드려요.
자주 묻는 질문 (FAQ)
Q1: 왜 APIYI와 Gemini 공식 API는 비동기(Asynchronous) 호출을 지원하지 않나요?
기술적인 이유:
-
Google 인프라의 제한: Google Gemini API의 하부 인프라는 현재 동기식 추론 모드만 지원합니다. 비동기 호출을 구현하려면 별도의 작업 큐와 상태 관리 시스템이 필요합니다.
-
개발 복잡도: 비동기 호출을 구현하려면 다음과 같은 기능이 필요합니다.
- 작업 큐 관리
- 작업 상태의 영속화(Persistence)
- Webhook 콜백 메커니즘
- 실패 시 재시도 및 보상 로직
-
사용자 요구사항의 우선순위: 대부분의 사용자는 실시간으로 이미지를 생성하기를 원하며, 동기 호출만으로도 80% 이상의 시나리오를 충족할 수 있습니다.
해결 방법:
- 현재: 멀티스레딩/멀티프로세싱을 사용하여 동기 인터페이스를 병렬로 호출하세요.
- 미래: APIYI는 2026년 2분기에 비동기 호출 기능을 출시할 계획입니다.
Q2: APIYI의 OSS URL 이미지는 영구적으로 저장되나요?
저장 정책:
| 저장 기간 | 설명 | 권장 시나리오 |
|---|---|---|
| 7일 | 기본 7일간 저장 후 자동 삭제 | 임시 미리보기, 테스트 생성 |
| 30일 | 유료 사용자는 30일까지 연장 가능 | 단기 프로젝트, 이벤트 소재 |
| 영구 | 사용자가 직접 자신의 OSS로 다운로드 | 장기 사용, 상업 프로젝트 |
권장 방법:
import requests
# 이미지 생성 및 URL 획득
result = generate_image_sync(prompt="A beautiful landscape", size="4096x4096")
temp_url = result['data'][0]['url']
print(f"임시 URL: {temp_url}")
# 이미지를 로컬 또는 자신의 OSS로 다운로드
image_response = requests.get(temp_url)
with open("permanent_image.png", "wb") as f:
f.write(image_response.content)
# 또는 자신의 OSS에 업로드 (Alibaba Cloud OSS 예시)
import oss2
auth = oss2.Auth('YOUR_ACCESS_KEY', 'YOUR_SECRET_KEY')
bucket = oss2.Bucket(auth, 'oss-cn-beijing.aliyuncs.com', 'your-bucket')
bucket.put_object('images/permanent_image.png', image_response.content)
주의: APIYI에서 제공하는 OSS URL은 임시 저장용으로, 빠른 미리보기와 테스트에 적합합니다. 장기간 사용해야 하는 이미지는 즉시 로컬이나 본인의 클라우드 스토리지로 다운로드하시기 바랍니다.
Q3: 동기 호출 시 타임아웃(Timeout)을 방지하려면 어떻게 해야 하나요?
타임아웃 방지를 위한 3가지 핵심 설정:
-
올바른 타임아웃 시간 설정:
# ✅ 올바른 예: 연결(Connect)과 읽기(Read) 타임아웃을 각각 설정 timeout=(10, 600) # (연결 타임아웃 10초, 읽기 타임아웃 600초) # ❌ 잘못된 예: 단일 값만 설정 timeout=600 # 연결 타임아웃에만 적용될 수 있음 -
HTTP 포트 인터페이스 사용:
# ✅ 권장: APIYI HTTP 포트를 사용하여 HTTPS 핸드셰이크 오버헤드 방지 url = "http://api.apiyi.com:16888/v1/images/generations" # ⚠️ 선택 사항: HTTPS 인터페이스, TLS 핸드셰이크 시간이 추가됨 url = "https://api.apiyi.com/v1/images/generations" -
재시도 메커니즘 구현:
from requests.adapters import HTTPAdapter from requests.packages.urllib3.util.retry import Retry # 재시도 전략 설정 retry_strategy = Retry( total=3, # 최대 3번 재시도 status_forcelist=[429, 500, 502, 503, 504], # 해당 상태 코드에 대해서만 재시도 backoff_factor=2 # 지수 백오프(Exponential Backoff): 2s, 4s, 8s ) adapter = HTTPAdapter(max_retries=retry_strategy) session = requests.Session() session.mount("http://", adapter) # 세션을 사용하여 요청 보내기 response = session.post( "http://api.apiyi.com:16888/v1/images/generations", json={...}, timeout=(10, 600) )
Q4: 프런트엔드에서 Nano Banana Pro API를 직접 호출해도 되나요?
프런트엔드 직접 호출을 권장하지 않는 이유:
- API Key 유출 위험: 프런트엔드 코드는 모든 사용자에게 API Key를 노출시킵니다.
- 브라우저 병렬 연결 제한: 브라우저는 동일 도메인에 대해 기본적으로 최대 6개의 병렬 연결만 허용합니다.
- 타임아웃 제한: 브라우저의
fetchAPI는 기본 타임아웃이 짧아 이미지 생성이 완료되기 전에 끊길 수 있습니다.
권장 아키텍처: 백엔드 프록시 모드:
// 프런트엔드 코드 (React 예시)
async function generateImage(prompt, size) {
// 자신의 백엔드 API 호출
const response = await fetch('https://your-backend.com/api/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_USER_TOKEN' // 사용자 인증 토큰
},
body: JSON.stringify({ prompt, size })
});
const result = await response.json();
return result.image_url; // APIYI OSS URL 반환
}
// 사용 예시
const imageUrl = await generateImage("A futuristic city", "4096x4096");
document.getElementById('result-image').src = imageUrl;
# 백엔드 코드 (Flask 예시)
from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
@app.route('/api/generate', methods=['POST'])
def generate():
# 사용자 토큰 검증
user_token = request.headers.get('Authorization')
if not verify_user_token(user_token):
return jsonify({"error": "Unauthorized"}), 401
data = request.json
# 백엔드에서 APIYI API 호출 (API Key가 프런트엔드에 노출되지 않음)
response = requests.post(
"http://api.apiyi.com:16888/v1/images/generations",
json={
"prompt": data['prompt'],
"size": data['size'],
"model": "nano-banana-pro",
"n": 1,
"response_format": "url"
},
headers={"Authorization": "Bearer YOUR_APIYI_API_KEY"}, # 백엔드에 안전하게 저장
timeout=(10, 600)
)
result = response.json()
return jsonify({"image_url": result['data'][0]['url']})
요약
Nano Banana Pro API의 동기 및 비동기 호출 핵심 포인트는 다음과 같습니다.
- 동기 호출 특징: 생성이 완료될 때까지 HTTP 연결을 유지하며 30
170초 동안 대기합니다. 따라서 긴 타임아웃 설정(300600초)이 필수적입니다. - 비동기 호출의 장점: 작업 ID를 즉시 반환하며 블로킹이 발생하지 않아 대량 처리나 백그라운드 작업에 적합합니다. 다만, 현재 APIYI와 Gemini 공식 API 모두 지원하지 않습니다.
- APIYI OSS URL 출력: base64 인코딩 방식과 비교해 응답 데이터 크기를 99.998% 줄일 수 있습니다. CDN 가속과 브라우저 캐싱을 지원하여 성능을 획기적으로 향상합니다.
- 현재의 베스트 프랙티스: 동기 호출과 멀티스레드 병렬 처리를 결합하고 OSS URL로 출력하세요. APIYI의 HTTP 포트 인터페이스를 통해 최적화된 타임아웃 설정을 적용하는 것이 좋습니다.
- 향후 계획: APIYI는 2026년 2분기에 작업 제출, 상태 조회, Webhook 콜백을 지원하는 비동기 호출 기능을 출시할 예정입니다.
APIYI(apiyi.com)를 통해 Nano Banana Pro API를 신속하게 통합해 보세요. 최적화된 HTTP 포트 인터페이스(http://api.apiyi.com:16888/v1), 독자적인 OSS URL 이미지 출력, 그리고 합리적인 타임아웃 설정을 제공하여 실시간 이미지 생성 및 대량 처리 시나리오에 가장 적합한 환경을 제공합니다.
작성자: APIYI 기술 팀 | 기술적인 문의 사항이 있으시면 APIYI(apiyi.com)를 방문하여 더 많은 대규모 언어 모델 연동 솔루션을 확인해 보세요.
