# Nano Banana 2 503 ‘Model is Overloaded’ 오류 해결: 재시도와 중단 기준

> 503 과부하 오류가 확인되면 지수 백오프와 지터를 적용하되, 시도 횟수와 총 대기 예산을 제한해야 합니다. 현재 Nano Banana 2 모델로 이미지를 생성하거나 편집하고, 이미지가 실제로 반환됐는지 확인하는 Python 예제를 제공합니다.

- URL: https://blog.laozhang.ai/ko/posts/nano-banana-2-503-overloaded-fix
- Published: 2026-03-09
- Updated: 2026-10-07
- Author: LaoZhang AI Team (https://blog.laozhang.ai/ko/about)
- Topic: AI 이미지 생성
- Tags: Nano Banana 2, 503 오류 해결, Gemini API, API 오류 처리

---
Nano Banana 2에서 **503 ‘Model is Overloaded’** 오류가 나오면 같은 요청을 연달아 보내지 말고, 횟수와 시간 예산을 정한 재시도로 대응합니다. 기다리는 간격에 무작위 지연을 넣고, 예산을 다 쓰면 작업을 보류하거나 대기열로 옮깁니다. 성공 여부는 HTTP 200이 아니라 **열 수 있는 이미지가 반환됐는지**로 판단합니다.

현재 [Google 모델 문서](https://ai.google.dev/gemini-api/docs/models/gemini-3.1-flash-image)의 Nano Banana 2 ID는 `gemini-3.1-flash-image`입니다. 아래 예제는 이 모델의 Gemini API 이미지 생성·편집에 맞춰 작성했습니다. Gemini 앱의 로딩 문제나 외부 서비스의 자체 오류 메시지는 먼저 그 서비스에서 확인해야 합니다.

## 재시도 전에 503과 다른 실패를 구분하세요

503은 요청을 받은 서비스가 일시적으로 처리할 수 없다는 신호입니다. 과부하나 유지보수 때 발생할 수 있지만, **응답 한 건으로 전 세계 모든 사용자의 장애를 확정할 수는 없습니다.** 외부 중계 서비스를 사용한다면 그 서비스가 직접 503을 반환했을 수도 있습니다. [HTTP 503의 정의](https://www.rfc-editor.org/rfc/rfc9110.html#section-15.6.4)는 서비스의 일시적인 이용 불가를 설명합니다.

먼저 발생 시각, 실제 호스트와 API 경로, 모델 ID, HTTP 상태 코드, 오류 본문, 요청 식별자, 걸린 시간을 남깁니다. 공유 로그에서 API 키, 사용자 이미지와 민감한 프롬프트는 제외합니다. 그다음 아래 분기에 따라 행동합니다.

| 확인한 결과 | 다음 행동 | 같은 요청의 자동 재전송 |
|---|---|---|
| HTTP 503, `UNAVAILABLE` 또는 과부하 메시지 | 제한된 백오프로 복구 시도 | 정한 예산 안에서만 |
| HTTP 429 | 응답의 제한 항목 확인, 요청 속도 축소 | 일시적인 제한인지 확인한 뒤 결정 |
| HTTP 400·402·403·404 | 요청 형식, 결제 전제, 권한, 모델·리소스 확인 | 조건을 고치기 전에는 중단 |
| HTTP 200이지만 이미지 없음 | 응답의 `parts`, 종료 사유와 차단 정보를 확인 | 503 재시도 대상으로 처리하지 않음 |
| 응답을 받지 못한 연결 끊김·클라이언트 timeout | 처리 완료 여부와 로그 확인 | 결과를 모르는 POST를 바로 반복하지 않음 |

429를 모두 분당 요청 제한으로 단정하지 마세요. 짧은 시간의 요청 제한과 하루 할당량 소진은 기다려야 하는 조건이 다릅니다. 하루 한도를 다 썼다면 짧은 백오프를 반복해도 해결되지 않습니다. Google의 [문제 해결 문서](https://ai.google.dev/gemini-api/docs/troubleshooting)는 일시적인 429·503에는 백오프와 지터를 사용하고, 잘못된 요청이나 권한 문제에는 다른 조치를 취하도록 안내합니다.

![503, 429, 요청 오류, 이미지 없는 200과 응답 없는 시간 초과를 나누는 진단도](https://blog.laozhang.ai/posts/ko/nano-banana-2-503-overloaded-fix/img/image-api-failure-branches.webp)

오류 메시지의 `deadline expired`와 내 코드에서 발생한 `TimeoutError`도 구분해야 합니다. 서버가 HTTP 503을 반환한 경우와 클라이언트가 응답을 기다리다 연결을 끊은 경우는 같은 실패가 아닙니다. 후자는 서버에서 이미지 생성이 끝났는지 모를 수 있습니다. 이미지 생성 POST의 중복 처리가 없다고 가정할 근거 없이 다시 보내면 작업과 비용이 중복될 수 있습니다. [HTTP 재시도 규칙](https://www.rfc-editor.org/rfc/rfc9110.html#section-9.2.2)도 비멱등 요청의 자동 재전송에는 별도 조건이 필요하다고 설명합니다.

현재 장애의 범위를 먼저 확인해야 한다면 [Nano Banana 2 공식 서버 상태와 ‘나만 안 됨’ 구분법](https://blog.laozhang.ai/ko/posts/is-nano-banana-2-down)을 참고하세요. Gemini API의 상태는 [AI Studio Status](https://aistudio.google.com/status)에서 확인하되, Gemini 앱이나 Vertex AI까지 같은 상태라고 확대하지 않습니다.

## 이미지 요청 하나에 재시도 예산 하나를 둡니다

복구 루프는 처음 요청을 포함한 **최대 시도 횟수**, 호출과 대기에 사용할 **시간 예산**, 대기 간격의 **상한**을 함께 관리해야 합니다. 횟수만 제한하면 느린 호출 때문에 사용자 대기 시간이 길어지고, 시간만 제한하면 빠르게 실패하는 요청이 지나치게 많이 나갈 수 있습니다.

예를 들어 처음 요청을 포함해 4회, 시간 예산 90초, 요청별 timeout 상한 30초, 첫 백오프 범위 0~1초로 설정할 수 있습니다. 이후 백오프 범위를 0~2초, 0~4초로 늘려 무작위로 기다립니다. 이 값들은 아래 코드를 설명하기 위한 **애플리케이션 설정 예시**이며, Google이 정한 복구 시간이나 성공률 기준이 아닙니다. 이미지 크기와 실제 처리 시간, 사용자에게 약속한 응답 시간을 보고 조정해야 합니다.

응답에 `Retry-After`가 있다면 그 지시보다 일찍 요청하지 않습니다. 이 헤더는 초 단위 정수 또는 HTTP 날짜일 수 있습니다. 남은 예산보다 긴 대기를 요구하면 짧게 잘라 재전송하는 대신 작업을 보류합니다. 헤더가 없을 때 지수 백오프와 지터로 요청 시점을 분산합니다. [Retry-After 형식](https://www.rfc-editor.org/rfc/rfc9110.html#section-10.2.3)은 HTTP 표준에 정의되어 있습니다.

재시도를 맡는 계층도 하나로 정합니다. 앱이 4회, SDK가 매번 5회 요청하면 전송이 최대 20회로 늘어날 수 있고, 중계 서비스의 재시도까지 겹치면 더 늘어납니다. Google의 문제 해결 문서에는 Python SDK가 자동으로 네 번 재시도한다고 적혀 있지만, 2026년 10월 6일 확인한 [`python-genai` main 소스](https://github.com/googleapis/python-genai/blob/main/google/genai/_api_client.py)는 `retry_options=None`일 때 한 번만 시도합니다. 설치한 모든 버전의 기본값이 같다고 가정하지 말고 명시적으로 설정하세요.

앱이 재시도를 맡는 SDK 구현이라면 [`HttpRetryOptions(attempts=1)`](https://github.com/googleapis/python-genai/blob/main/google/genai/types.py)처럼 내부 재시도를 끄는 방식이 필요합니다. `attempts`에는 최초 호출이 포함되며, `HttpOptions.timeout`의 단위는 밀리초입니다. SDK 오류를 처리할 때 [`APIError.code`는 정수](https://github.com/googleapis/python-genai/blob/main/google/genai/errors.py)이므로 `e.code == 503`으로 판별합니다. 문자열에서 ‘503’을 찾는 방식은 피합니다. 별도 [Interactions API 오류 문서](https://ai.google.dev/gemini-api/docs/api-errors)의 `service_unavailable` 같은 문자열 코드를 native `generateContent` SDK에 그대로 적용하지 않습니다.

## Python 예제: 생성·편집, 503 재시도, 이미지 확인까지

다음은 SDK 기본값에 의존하지 않는 직접 REST 예제입니다. Python 3.10 이상과 Pillow가 준비되어 있어야 합니다. 인증 정보는 운영 환경에서 안전하게 주입한 값을 함수 인수로 전달합니다. 텍스트 생성은 `source=None`, 이미지 편집은 이미 읽어 둔 `(MIME 타입, 이미지 바이트)`를 넘깁니다. 편집 원본은 호출 전에 로컬에서 읽어 고정하며 재시도마다 다시 업로드하는 별도 단계는 없습니다.

Gemini API의 [이미지 생성 문서](https://ai.google.dev/gemini-api/docs/generate-content/image-generation)에 따른 `contents.parts`, `responseModalities`, 응답의 `inlineData`를 사용합니다. 아래 코드는 이미지 바이트를 실제 디코딩한 뒤 저장하며, 텍스트만 있는 200 응답을 성공으로 반환하지 않습니다.

```python
import base64
import io
import json
import random
import time
import urllib.error
import urllib.request
from email.utils import parsedate_to_datetime
from pathlib import Path
from PIL import Image

ENDPOINT = (
    "https://generativelanguage.googleapis.com/v1/"
    "models/gemini-3.1-flash-image:generateContent"
)


def post_once(key, body, timeout):
    request = urllib.request.Request(
        ENDPOINT,
        data=json.dumps(body).encode("utf-8"),
        headers={"Content-Type": "application/json", "x-goog-api-key": key},
        method="POST",
    )
    try:
        with urllib.request.urlopen(request, timeout=timeout) as response:
            return response.status, dict(response.headers), response.read()
    except urllib.error.HTTPError as error:
        return error.code, dict(error.headers), error.read()


def retry_after(headers, wall_now):
    value = next(
        (v for k, v in headers.items() if k.lower() == "retry-after"), None
    )
    if value is None:
        return 0.0
    value = value.strip()
    if value.isdigit():
        return float(value)
    try:
        date = parsedate_to_datetime(value)
        if date.tzinfo is None:
            return 0.0
        return max(0.0, date.timestamp() - wall_now())
    except (ValueError, TypeError, OverflowError):
        return 0.0


def image_output(payload):
    for candidate in payload.get("candidates", []):
        parts = candidate.get("content", {}).get("parts", [])
        for part in parts:
            inline = part.get("inlineData") or {}
            mime = inline.get("mimeType", "")
            if not mime.startswith("image/") or not inline.get("data"):
                continue
            try:
                data = base64.b64decode(inline["data"], validate=True)
                with Image.open(io.BytesIO(data)) as image:
                    image.verify()
                with Image.open(io.BytesIO(data)) as image:
                    image.load()
                    width, height = image.size
                    suffix = {"PNG": ".png", "JPEG": ".jpg", "WEBP": ".webp"}.get(
                        image.format
                    )
                if width > 0 and height > 0 and suffix:
                    return data, suffix
            except Exception:
                continue
    return None


def generate_image(
    key, prompt, output_stem, source=None,
    max_attempts=4, budget=90.0, call_timeout=30.0,
    send=post_once, now=time.monotonic, sleep=time.sleep,
    wall_now=time.time, uniform=random.uniform,
):
    if max_attempts < 1 or budget <= 0 or call_timeout <= 0:
        raise ValueError("invalid retry budget")
    parts = [{"text": prompt}]
    if source is not None:
        mime, data = source
        parts.append({"inlineData": {
            "mimeType": mime,
            "data": base64.b64encode(data).decode("ascii"),
        }})
    body = {
        "contents": [{"parts": parts}],
        "generationConfig": {"responseModalities": ["TEXT", "IMAGE"]},
    }
    deadline = now() + budget
    attempts = 0
    for attempt in range(max_attempts):
        remaining = deadline - now()
        if remaining <= 0:
            return {"state": "deferred", "reason": "time_budget", "attempts": attempts}
        attempts += 1
        try:
            code, headers, raw = send(key, body, min(call_timeout, remaining))
        except (TimeoutError, OSError):
            return {"state": "unknown", "reason": "transport", "attempts": attempts}
        if code == 200:
            try:
                payload = json.loads(raw)
                result = image_output(payload)
            except (ValueError, TypeError, AttributeError):
                result = None
            if result is None:
                return {"state": "inspect", "reason": "no_valid_image", "attempts": attempts}
            data, suffix = result
            output = Path(str(output_stem) + suffix)
            output.write_bytes(data)
            return {"state": "completed", "path": str(output), "attempts": attempts}
        if code != 503:
            return {"state": "inspect", "http": code, "attempts": attempts}
        hint = retry_after(headers, wall_now)
        if attempt + 1 == max_attempts:
            return {"state": "deferred", "reason": "attempt_budget",
                    "attempts": attempts, "retry_after_seconds": hint}
        delay = max(
            hint,
            uniform(0.0, min(8.0, 2.0 ** attempt)),
        )
        if delay >= deadline - now():
            return {"state": "deferred", "reason": "retry_after_or_budget",
                    "attempts": attempts, "retry_after_seconds": delay}
        sleep(delay)
    raise AssertionError("unreachable")
```

사용 방식은 다음과 같습니다. `key`는 호출자가 이미 안전하게 준비한 값입니다. 아래는 연결 방법을 보여 주는 호출 예시이며, 실행하면 실제 이미지 요청이 발생합니다.

```python
# 텍스트로 새 이미지 생성
result = generate_image(key, "흰 배경 위의 파란 도자기 컵", "result")

# 원본 이미지를 넣어 편집: 실제 파일 형식과 MIME 타입을 맞춥니다.
source = ("image/png", Path("input.png").read_bytes())
result = generate_image(key, "컵의 색을 초록색으로 바꾸세요", "edited", source=source)
print(result)
```

이 예제의 `timeout`은 `urllib`에 전달하는 초 단위 네트워크 timeout입니다. 전체 실행을 정확히 90초에 강제 종료하는 장치는 아닙니다. 루프는 경과 시간을 확인해 예산이 지난 뒤 **새 요청이나 다음 대기**를 시작하지 않으며, 각 전송에도 남은 시간 이하의 timeout을 전달합니다. 작업 전체에 엄격한 종료 시각이 필요하다면 별도 워커의 실행 기한도 설정해야 합니다. 그 기한에 걸려 연결이 끊긴 작업 역시 처리 결과를 모르는 상태로 남깁니다.

반환 상태는 후속 처리와 연결합니다.

- `completed`: 저장된 파일을 열어 확인하고 작업을 완료 처리합니다.
- `deferred`: 작업 ID, 원래 입력, 시도 수와 다음 실행 가능 시각을 저장합니다. `retry_after_seconds`가 있으면 응답을 받은 시각에 더해 다음 실행 가능 시각을 저장하고, 그 전에 재개하지 않습니다.
- `inspect`: 429·권한 오류·이미지 없는 응답 등 원인별 점검으로 이동합니다. 해당 응답의 본문과 종료 사유를 접근이 제한된 로그에 보존하세요.
- `unknown`: 응답을 못 받아 완료 여부를 모릅니다. 로그·요청 식별자로 확인하고, 확인 없이 새 POST를 보내지 않습니다.

파일 저장 실패는 코드 밖으로 예외가 전달됩니다. 이미지가 이미 생성된 뒤 저장만 실패한 상황을 503으로 바꿔 다시 생성하지 않도록 별도로 처리하세요. 여러 워커에서는 같은 출력 경로를 공유하지 말고 작업 ID별 경로를 사용합니다.

이 예제의 분기는 가짜 응답·가짜 시계와 합성 이미지로 로컬 검증했습니다. 실제 Gemini API 호출이나 현재 성공률·응답 시간 측정은 수행하지 않았습니다. `completed`는 이미지 파일의 디코딩 가능성을 확인한 상태이며, 편집 지시를 잘 따랐는지나 최종 화질까지 판정하지는 않습니다.

## 동시 요청이 많다면 복구 요청부터 줄이세요

개별 요청에 백오프를 넣어도 워커 수가 많으면 재시도가 한꺼번에 몰릴 수 있습니다. 모델과 실제 API 경로별로 동시 실행 수를 제한하고, 재시도도 신규 요청과 같은 실행 슬롯을 사용하게 합니다. 대기 중에는 슬롯을 돌려주고, 다음 시도 직전에 다시 확보하는 방식으로 관리할 수 있습니다. 무제한 대기열 대신 작업 수와 작업 만료 시간을 제한하세요.

503이 이어질 때는 **서킷 브레이커**로 새 전송을 잠시 멈출 수 있습니다. 정상 상태에서는 정해진 동시 실행 수 안에서 요청하고, 실패 조건을 넘으면 회로를 열어 새 작업을 보류합니다. 일정 시간이 지난 뒤 반개방 상태에서는 **확인 요청 하나만** 통과시킵니다.

![닫힘·열림·반개방에서 단일 확인 요청을 예약하고 유효한 이미지로 점진 재개하는 흐름](https://blog.laozhang.ai/posts/ko/nano-banana-2-503-overloaded-fix/img/single-probe-circuit-control.webp)

반개방을 단순히 `return True`로 구현하면 여러 스레드가 동시에 확인 요청을 보낼 수 있습니다. ‘확인 요청이 진행 중인가’를 확인하는 동작과 예약하는 동작을 하나의 잠금 안에서 처리해야 합니다. 여러 프로세스나 서버를 쓰면 로컬 변수 대신 공유 저장소의 원자적 예약이 필요합니다. 예약에는 만료 시간을 두어 워커가 중단됐을 때 영원히 막히지 않도록 합니다.

동시 실행 슬롯과 확인 요청 예약을 모두 확보한 뒤 전송하고, 확보에 실패하면 전송 없이 대기열로 보냅니다. 확인 요청에서 유효한 이미지가 나오면 동시 실행 수를 조금씩 늘립니다. 다시 503이 나오면 회로를 열고 다음 확인 시각을 늦춥니다. 400·403이나 이미지 없는 200은 별도 요청 문제로 기록하며, 그 결과만으로 서비스가 복구됐다고 판단하지 않습니다. 회로를 연 뒤 아직 진행 중이던 이전 요청이 성공하더라도 그 오래된 결과가 새 상태를 덮어쓰지 않도록 상태 세대 번호를 함께 확인합니다.

몇 회 실패 후 얼마 동안 멈출지는 서비스 목표와 로그를 보고 정할 운영 정책입니다. 모든 환경에서 통하는 ‘5회 실패, 30초 뒤 복구’ 기준은 없습니다. 확인 요청 자체도 이미지 생성이므로 주기적인 무제한 테스트 대신 실제 대기 작업 하나를 활용하고 시도 예산에 포함합니다.

## 예산을 다 썼다면 대기열·대체 모델·Batch 중에서 선택합니다

**결과가 같아야 한다면 대기열**이 우선입니다. 입력 이미지와 프롬프트, 모델 ID, 작업 상태를 저장하고 사용자가 ‘접수됨’과 ‘완료됨’을 구분할 수 있게 합니다. 중복 클릭에는 같은 로컬 작업 ID를 반환하고, 워커가 작업을 원자적으로 확보하게 하세요. 이 방식은 내 시스템의 중복 접수를 줄이며, Google API가 같은 POST를 자동 중복 제거한다는 뜻은 아닙니다. 재개한 작업에도 전체 시도 한도와 만료 시간을 이어서 적용해야 매번 예산이 초기화되는 무한 반복을 피할 수 있습니다.

**다른 결과를 허용할 수 있다면 이미지 모델로 대체**할 수 있습니다. 먼저 이미지 입력·출력 지원, 편집 방식, 해상도와 비율, 데이터 처리 조건, 비용 상한을 확인합니다. 텍스트 전용 `gemini-2.5-flash`로 바꾸는 것은 이미지 생성 복구가 아닙니다. 다른 모델은 원래 편집 결과와 달라질 수 있으므로 사용자가 허용한 품질과 비용 범위에서만 선택합니다. Vertex AI로 옮기는 경우에는 인증과 API 규칙도 달라져 단순히 모델 ID만 교체할 수 없습니다. 대체 경로 역시 이미지 검증과 시도 예산이 필요하며, 응답 없는 원래 작업의 상태를 모른다면 즉시 병렬로 새 생성 작업을 시작하지 않습니다.

**긴급하지 않은 대량 작업이라면 Batch**를 검토합니다. 현재 Nano Banana 2 모델 문서에는 Batch 지원이 표시되어 있습니다. [Batch API 문서](https://ai.google.dev/gemini-api/docs/batch-api)는 비동기 처리의 목표 시간을 24시간으로 안내하지만, 이는 완료 보장이나 ‘503 면역’ 약속이 아닙니다. 작업은 실패·취소·만료될 수 있고, 성공 상태여도 개별 항목의 오류와 실제 이미지 출력을 확인해야 합니다. 제출 뒤에는 작업 이름을 저장해 상태를 조회하고, 조회 실패만으로 같은 전체 작업을 다시 제출하지 않습니다.

특정 UTC 시간대가 모든 사용자에게 더 안전하다는 현재 측정 근거도 없습니다. 대량 작업의 시간대를 바꾸고 싶다면 자신의 동일한 모델·경로·입력 조건에서 요청 수, 503 비율, 이미지 완료 수와 소요 시간을 비교하세요. 근거 없는 시간대별 성공률로 재시도 횟수를 늘리는 대신, 로그가 보여 주는 요청 압력과 대기열 상태에 맞춰 조정합니다.

## 자주 묻는 질문

### 503 ‘Model is Overloaded’는 코드를 바꿔도 해결되지 않나요?

서버의 용량을 클라이언트 코드로 늘릴 수는 없지만, 재시도 폭주를 막고 유효한 이미지를 확인하며 실패 작업을 보류하도록 코드를 고칠 수 있습니다. 이는 앱이 실패를 다루는 방법을 개선하는 것이며, 정해진 시간 안에 Google이 복구된다는 보장은 아닙니다. 먼저 실제 503 응답을 확인한 뒤 제한된 복구 루프를 적용합니다.

### 실패한 503 요청은 과금되지 않나요?

모든 503이 무료라고 단정할 근거는 없습니다. Google의 [결제 FAQ](https://ai.google.dev/gemini-api/docs/billing)는 실패한 **400 또는 500** 요청에는 토큰 요금이 없지만 할당량에는 포함된다고 설명합니다. 이 문구를 503 전체, 응답 없는 timeout, 외부 중계 서비스의 환불 정책으로 확대하지 마세요. 실제 사용량과 제공업체의 기록을 확인하고, 재시도·대체 생성에는 비용 상한을 둡니다.

### 유료 등급이나 API 키 변경으로 503을 우회할 수 있나요?

유료 등급 변경이 503 용량 문제를 해결한다는 보장은 없습니다. 429라면 먼저 실제 제한 항목을 확인해야 합니다. 키나 프로젝트를 번갈아 써서 제한을 피하는 대신 요청 속도를 낮추고 해당 조건에 맞춰 기다립니다. 외부 서비스에서만 503이 발생한다면 그 서비스의 응답 출처와 로그부터 확인합니다.

### 200이 왔는데 이미지가 없으면 다시 보내면 되나요?

자동으로 503 재시도 루프에 넣지 않습니다. 응답의 `candidates[].content.parts`에 이미지가 있는지, 텍스트만 반환됐는지, 종료 사유나 차단 정보가 있는지 확인합니다. 안전 차단 외에도 생성 결과나 파서 문제일 수 있습니다. 예제는 이미지 바이트를 디코딩하지 못하면 `inspect`로 멈춥니다.

### Batch로 보내면 결국 모든 이미지가 완성되나요?

보장되지 않습니다. [Batch 문서](https://ai.google.dev/gemini-api/docs/batch-api)의 24시간은 처리 목표이며, 작업 상태와 각 항목의 오류를 따로 확인해야 합니다. 당장 결과가 필요 없는 작업의 전달 방식으로 선택하고, 실패 항목과 만료 작업을 처리할 정책을 함께 준비합니다.

## 공식 문서

요청 파라미터, 가격, 과금 규칙은 LaoZhang API 개발자 문서를 기준으로 합니다: [이미지 생성 과금과 실패 처리](https://docs.laozhang.ai/en/api-capabilities/image-billing-and-failures).

*안내: [laozhang.ai는 이 블로그 운영팀의 자사 서비스입니다](https://blog.laozhang.ai/ko/about#laozhang). 그 가격은 독립적인 비교가 아니라 자사 제시 가격입니다.*

## 참고 자료

이 글이 링크한 외부 페이지를 본문에 나온 순서대로 정리했습니다. 마지막 업데이트: 2026-10-07.

- [Google 모델 문서](https://ai.google.dev/gemini-api/docs/models/gemini-3.1-flash-image) (ai.google.dev)
- [HTTP 503의 정의](https://www.rfc-editor.org/rfc/rfc9110.html) (rfc-editor.org)
- [문제 해결 문서](https://ai.google.dev/gemini-api/docs/troubleshooting) (ai.google.dev)
- [AI Studio Status](https://aistudio.google.com/status) (aistudio.google.com)
- [python-genai main 소스](https://github.com/googleapis/python-genai/blob/main/google/genai/_api_client.py) (github.com)
- [HttpRetryOptions(attempts=1)](https://github.com/googleapis/python-genai/blob/main/google/genai/types.py) (github.com)
- [APIError.code는 정수](https://github.com/googleapis/python-genai/blob/main/google/genai/errors.py) (github.com)
- [Interactions API 오류 문서](https://ai.google.dev/gemini-api/docs/api-errors) (ai.google.dev)
- [이미지 생성 문서](https://ai.google.dev/gemini-api/docs/generate-content/image-generation) (ai.google.dev)
- [Batch API 문서](https://ai.google.dev/gemini-api/docs/batch-api) (ai.google.dev)
- [결제 FAQ](https://ai.google.dev/gemini-api/docs/billing) (ai.google.dev)
