> ## Documentation Index
> Fetch the complete documentation index at: https://docs.laozhang.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Nano Banana Pro API 이미지 편집 사용법

> LaoZhang API에서 gemini-3-pro-image로 이미지를 편집·합성합니다. 참조 이미지 최대 14장, 1K~4K 출력, 공개 URL 입력과 바로 실행할 수 있는 코드를 제공합니다.

Nano Banana Pro(`gemini-3-pro-image`)는 텍스트 지시만으로 세부를 고치거나 사진 스타일을 바꾸고, 여러 이미지를 합쳐 새 이미지를 만듭니다. 이 페이지는 LaoZhang API의 두 요청 형식을 모두 다루며, 편집은 크기와 관계없이 호출마다 고정 가격 하나로 과금됩니다.

| 항목 | 내용 |
| - | - |
| 모델 ID | `gemini-3-pro-image` |
| 엔드포인트 | Gemini 네이티브 `generateContent`는 종횡비와 크기를 지정할 수 있고, OpenAI 호환 chat completions는 같은 편집을 크기 설정 없이 받음 |
| 참조 이미지 | 요청당 최대 14장 |
| 이미지 입력 | Base64 `inlineData` 또는 `fileData`에 공개 URL |
| 출력 크기 | `1K`(기본값), `2K`, `4K` |
| 종횡비 | 10종, `aspectRatio`로 지정 |
| 출력 | 응답에 Base64 이미지로 포함되며, 디코딩해 저장 |
| 마스크 | 없음. 바꿀 영역을 지시문으로 설명 |
| 가격 | 크기와 관계없이 호출당 \$0.09(2026년 9월 24일 기준 공개 가격, [AI 모델 API 가격표](https://docs.laozhang.ai/ko/models.md) 참고) |
| 과금 | HTTP 200 응답은 이미지가 없어도 한 번 과금됨. [Nano Banana 개요](https://docs.laozhang.ai/ko/api-capabilities/nano-banana-image.md)의 과금 절 참고 |

텍스트만으로 이미지를 만들려면 [Nano Banana Pro](https://docs.laozhang.ai/ko/api-capabilities/nano-banana-pro-image.md) 이미지 생성 가이드를 참고하세요.

## 시작하기 전에

**1. API 키 발급**

[토큰 관리](https://api.laozhang.ai/token)에서 토큰 생성(创建令牌) 창을 열고, **과금 방식**(计费模式)을 **사용량 우선**(按量优先, 권장) 또는 **건당 과금**(按次计费)으로 설정한 뒤 **생성**(创建)을 클릭합니다. Nano Banana Pro에는 호출당 가격만 있어 사용량 과금(按量计费) 키로는 호출할 수 없습니다. 요청이 언제 과금되는지는 [Nano Banana 개요](https://docs.laozhang.ai/ko/api-capabilities/nano-banana-image.md)의 과금 절에서 설명합니다.

![LaoZhang API 콘솔의 토큰 생성 창. 과금 방식이 건당 과금(按次计费)으로 설정되어 있음](https://mintcdn.com/laozhangai-edd05f2c/_loZ0Jy0ZI__xJ9z/images/token-create-per-request.png?fit=max\&auto=format\&n=_loZ0Jy0ZI__xJ9z\&q=85\&s=1fdceb804bb3ad50f83a21ec65b4d807)

**2. 키 설정과 의존성 설치**

```bash theme={null}
export LAOZHANG_API_KEY="sk-..."  # LaoZhang API 키로 바꾸세요
python -m pip install openai requests
```

**3. cURL용 저장 함수 추가**

cURL 예제에는 `jq`가 필요합니다. 아래 셸 함수를 정의해 두면 Gemini 네이티브 응답의 마지막 이미지(중간 이미지가 함께 오더라도 최종 결과)를 `mimeType`에 맞는 확장자로 저장합니다.

```bash theme={null}
save_image() {
  local image='[.candidates[]?.content.parts[]? | select(.inlineData and (.thought | not))][-1].inlineData'
  local ext
  case "$(jq -r "$image.mimeType" "$1")" in
    image/png) ext=png ;;
    image/jpeg) ext=jpg ;;
    image/webp) ext=webp ;;
    *) jq '{error, promptFeedback, finishReasons: [.candidates[]?.finishReason]}' "$1"; return 1 ;;
  esac
  jq -r "$image.data" "$1" | base64 --decode > "$2.$ext" && echo "저장됨: $2.$ext"
}
```

응답에 이미지가 없으면 이 함수는 대신 `error`, `promptFeedback`, `finishReason` 필드를 출력합니다.

## 로컬 이미지 편집

요청은 `POST https://api.laozhang.ai/v1beta/models/gemini-3-pro-image:generateContent`로 보냅니다. `parts`에 지시문을 먼저, 이미지를 그 뒤에 넣고, 로컬 파일은 파일과 일치하는 `mimeType`을 붙인 `inlineData` 파트로 보냅니다.

> [tab] Python
>
> 아래 스크립트를 `nano_banana_pro_edit.py`로 저장하세요. 지시문과 함께 로컬 이미지 1\~14장을 보내고, 응답에 들어 있는 이미지를 모두 저장합니다.
>
> ```python theme={null}
> """Gemini 네이티브 경로에서 Nano Banana Pro(gemini-3-pro-image)로 이미지를 편집하거나 합성합니다."""
> import argparse
> import base64
> import os
> import sys
> from pathlib import Path
>
> import requests
>
> URL = "https://api.laozhang.ai/v1beta/models/gemini-3-pro-image:generateContent"
> RATIOS = ["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"]
> MIME_TYPES = {".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".webp": "image/webp"}
> EXTENSIONS = {"image/png": "png", "image/jpeg": "jpg", "image/webp": "webp"}
>
> parser = argparse.ArgumentParser(description="이미지 한 장을 편집하거나, 참조 이미지를 최대 14장까지 합성합니다.")
> parser.add_argument("prompt", help="편집 지시문")
> parser.add_argument("images", nargs="+", help="로컬 PNG, JPEG, WebP 파일 1~14장")
> parser.add_argument("--ratio", choices=RATIOS, help="출력 종횡비. 생략하면 입력 이미지를 따릅니다")
> parser.add_argument("--size", default="1K", choices=["1K", "2K", "4K"])
> parser.add_argument("--out", default="pro-edit", help="확장자를 뺀 출력 파일 이름")
> args = parser.parse_args()
> if len(args.images) > 14:
>     sys.exit("참조 이미지는 최대 14장까지 보낼 수 있습니다.")
>
> parts = [{"text": args.prompt}]
> for path in args.images:
>     mime = MIME_TYPES.get(Path(path).suffix.lower())
>     if mime is None:
>         sys.exit(f"PNG, JPEG, WebP 파일을 사용하세요: {path}")
>     data = base64.b64encode(Path(path).read_bytes()).decode("ascii")
>     parts.append({"inlineData": {"mimeType": mime, "data": data}})
>
> image_config = {"imageSize": args.size}
> if args.ratio:
>     image_config["aspectRatio"] = args.ratio
>
> response = requests.post(
>     URL,
>     headers={"Authorization": f"Bearer {os.environ['LAOZHANG_API_KEY']}"},
>     json={
>         "contents": [{"role": "user", "parts": parts}],
>         "generationConfig": {"responseModalities": ["IMAGE"], "imageConfig": image_config},
>     },
>     timeout=300,
> )
> if response.status_code != 200:
>     sys.exit(f"HTTP {response.status_code}: {response.text[:500]}")
>
> result = response.json()
> images = [
>     part["inlineData"]
>     for candidate in result.get("candidates") or []
>     for part in (candidate.get("content") or {}).get("parts") or []
>     if "inlineData" in part and not part.get("thought")
> ]
> if not images:
>     reasons = [candidate.get("finishReason") for candidate in result.get("candidates") or []]
>     sys.exit(f"반환된 이미지가 없습니다: {result.get('promptFeedback') or reasons}")
> for number, image in enumerate(images, start=1):
>     suffix = "" if number == 1 else f"-{number}"
>     output = Path(f"{args.out}{suffix}.{EXTENSIONS.get(image['mimeType'], 'bin')}")
>     output.write_bytes(base64.b64decode(image["data"]))
>     print("저장됨:", output)
> ```
>
> 고양이 사진에 모자를 씌워 2K로 저장합니다.
>
> ```bash theme={null}
> python nano_banana_pro_edit.py "고양이에게 작은 파란색 마법사 모자를 씌워 주세요. 자세, 털, 배경은 그대로 유지하세요." cat.jpg --size 2K --out pro-cat-hat
> ```

> [tab] cURL
>
> 큰 이미지가 셸 인자 길이 제한을 넘지 않도록 파일을 인코딩해 `jq`로 본문을 만듭니다. `mimeType`은 파일과 일치해야 합니다(이 JPEG는 `image/jpeg`).
>
> ```bash theme={null}
> base64 < cat.jpg | tr -d '\n' > cat.b64
> jq -n --rawfile image cat.b64 '{
>   contents: [{
>     role: "user",
>     parts: [
>       {text: "고양이에게 작은 파란색 마법사 모자를 씌워 주세요. 자세, 털, 배경은 그대로 유지하세요."},
>       {inlineData: {mimeType: "image/jpeg", data: $image}}
>     ]
>   }],
>   generationConfig: {
>     responseModalities: ["IMAGE"],
>     imageConfig: {imageSize: "2K"}
>   }
> }' > pro-edit-request.json
>
> curl --fail-with-body --max-time 300 \
>   "https://api.laozhang.ai/v1beta/models/gemini-3-pro-image:generateContent" \
>   -H "Authorization: Bearer $LAOZHANG_API_KEY" \
>   -H "Content-Type: application/json" \
>   --data-binary @pro-edit-request.json \
>   -o pro-edit-response.json
>
> save_image pro-edit-response.json pro-cat-hat
> ```

두 예제 모두 `aspectRatio`를 생략했으므로, 결과는 Google 기본 동작대로 입력 이미지 크기에 맞춰집니다. 모양을 바꾸려면 `aspectRatio`(또는 `--ratio`)를 추가하세요. 종횡비와 크기별 픽셀 수는 [Nano Banana Pro](https://docs.laozhang.ai/ko/api-capabilities/nano-banana-pro-image.md) 페이지의 출력 크기 절에 있습니다.

4K 편집은 1K보다 오래 걸리므로 클라이언트 타임아웃을 넉넉하게 잡으세요. 예제는 300초까지 기다립니다.

## 참조 이미지 합성

지시문 뒤에 프롬프트에서 언급하는 순서대로 파일을 최대 14장 나열하고, 프롬프트에서 각 이미지의 역할을 밝히세요.

```bash theme={null}
python nano_banana_pro_edit.py "첫 번째 이미지의 인물에게 두 번째 이미지의 재킷을 입히고, 세 번째 이미지의 거리에 서 있게 해 주세요. 인물의 얼굴과 헤어스타일은 그대로 유지하세요." person.jpg jacket.png street.jpg --ratio 3:4 --size 2K --out pro-outfit
```

Google은 14장의 참조 이미지를 용도별로 나눕니다. 한 요청에서 Nano Banana Pro가 받는 최대 장수는 다음과 같습니다.

* **객체 이미지 6장**: 제품이나 소품처럼 결과에 충실하게 나타나야 하는 대상
* **캐릭터 이미지 5장**: 연작에서 인물을 일관되게 유지
* **스타일 이미지 3장**: 색감이나 붓 터치 같은 전체적인 느낌 지정

요청에는 이미지의 역할을 지정하는 필드가 없으므로, 각 이미지를 어떻게 쓸지 지시문에 적으세요.

## 공개 URL 이미지 편집

Gemini 네이티브 경로에서는 Base64 대신 `fileData` 파트에 URL을 넣어 이미지를 보낼 수도 있습니다.

```bash theme={null}
curl --fail-with-body --max-time 300 \
  "https://api.laozhang.ai/v1beta/models/gemini-3-pro-image:generateContent" \
  -H "Authorization: Bearer $LAOZHANG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{
      "role": "user",
      "parts": [
        {"text": "창문으로 따뜻한 저녁 햇살이 들어오게 해 주세요. 가구와 배치는 그대로 유지하세요."},
        {"fileData": {"fileUri": "https://example.com/images/living-room.png", "mimeType": "image/png"}}
      ]
    }],
    "generationConfig": {
      "responseModalities": ["IMAGE"],
      "imageConfig": {"aspectRatio": "3:2", "imageSize": "2K"}
    }
  }' \
  -o pro-url-edit-response.json

save_image pro-url-edit-response.json pro-living-room
```

`fileUri`를 실제 이미지의 공개 HTTPS 주소로 바꾸고, `mimeType`을 이미지 형식에 맞추세요. 이미지는 요청 중에 해당 주소에서 내려받으므로 로그인, 쿠키, 봇 검사 없이 열려야 합니다. 내려받을 수 없다면 파일을 받아 `inlineData`로 보내세요.

* **요청이 20MB를 넘을 것 같으면 URL을 쓰세요.** 요청 본문 전체를 20MB 이내로 유지하고, `inlineData`로 보내는 이미지는 합계 약 15MB 이하로 맞추세요. 그보다 큰 이미지는 `fileData`로 넘기거나 먼저 줄이세요.
* 사이트의 `robots.txt`가 이미지 경로에 대한 크롤러 접근을 막지 않아야 합니다. 서명된 URL은 대기열과 재시도 시간을 감안해 최소 30분 동안 유효해야 합니다.
* `fileData` 파트와 `inlineData` 파트는 참조 순서대로 같은 `parts` 배열에 함께 쓸 수 있습니다. 전체 조건은 [Nano Banana 개요](https://docs.laozhang.ai/ko/api-capabilities/nano-banana-image.md)의 큰 이미지와 이미지 URL 절에 있습니다.

## OpenAI 호환 경로 사용

앱이 이미 OpenAI SDK를 쓴다면 chat completions로 편집을 보낼 수 있습니다. 지시문과 이미지를 한 사용자 메시지에 `image_url` 파트로 넣으며, 로컬 파일은 데이터 URL로, 원격 이미지는 공개 HTTPS URL로 보냅니다.

이 경로에는 종횡비와 크기 설정이 없으므로, 2K·4K나 고정 종횡비가 필요하면 Gemini 네이티브 경로를 쓰세요. 이미지는 `message.content` 안에 Base64 데이터 URL로 들어옵니다. 아래 스크립트를 `nano_banana_pro_chat_edit.py`로 저장하세요.

```python theme={null}
"""OpenAI 호환 경로로 Nano Banana Pro 이미지를 편집하거나 합성합니다."""
import argparse
import base64
import os
import re
import sys
from pathlib import Path

from openai import OpenAI

MIME_TYPES = {".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".webp": "image/webp"}
EXTENSIONS = {"png": "png", "jpeg": "jpg", "jpg": "jpg", "webp": "webp"}

parser = argparse.ArgumentParser(description="chat completions로 이미지 한 장을 편집하거나 여러 장을 합성합니다.")
parser.add_argument("prompt", help="편집 지시문")
parser.add_argument("images", nargs="+", help="로컬 PNG, JPEG, WebP 파일 또는 공개 HTTPS URL")
parser.add_argument("--out", default="pro-chat-edit", help="확장자를 뺀 출력 파일 이름")
args = parser.parse_args()

content = [{"type": "text", "text": args.prompt}]
for source in args.images:
    if source.startswith("https://"):
        url = source  # 공개 이미지 URL은 그대로 보냅니다
    else:
        mime = MIME_TYPES.get(Path(source).suffix.lower())
        if mime is None:
            sys.exit(f"PNG, JPEG, WebP 파일을 사용하세요: {source}")
        url = f"data:{mime};base64," + base64.b64encode(Path(source).read_bytes()).decode("ascii")
    content.append({"type": "image_url", "image_url": {"url": url}})

# max_retries=0: 타임아웃 뒤 자동 재시도하면 이미지가 두 번 생성되어 두 번 과금될 수 있습니다
client = OpenAI(api_key=os.environ["LAOZHANG_API_KEY"], base_url="https://api.laozhang.ai/v1", timeout=300, max_retries=0)
reply = client.chat.completions.create(
    model="gemini-3-pro-image",
    messages=[{"role": "user", "content": content}],
)
text = reply.choices[0].message.content or ""

found = re.findall(r"data:image/(png|jpe?g|webp);base64,([A-Za-z0-9+/=]+)", text)
if not found:
    sys.exit(f"반환된 이미지가 없습니다: {text[:300]}")
for number, (kind, encoded) in enumerate(found, start=1):
    suffix = "" if number == 1 else f"-{number}"
    output = Path(f"{args.out}{suffix}.{EXTENSIONS[kind]}")
    output.write_bytes(base64.b64decode(encoded + "=" * (-len(encoded) % 4)))
    print("저장됨:", output)
```

한 이미지의 화풍을 다른 이미지에 적용합니다.

```bash theme={null}
python nano_banana_pro_chat_edit.py "첫 번째 이미지의 색감과 붓 터치를 두 번째 이미지의 장면에 적용해 주세요." style.jpg photo.jpg --out pro-chat-restyle
```

## 응답 처리

* **Gemini 네이티브**: 각 이미지는 `candidates[].content.parts[]`의 `inlineData` 파트이며 `mimeType`과 Base64 `data`를 가집니다.
  * `thought: true`로 표시된 파트는 건너뛰세요. Pro는 렌더링 전에 사고하며, 복잡한 편집에서는 결과와 함께 중간 이미지가 올 수 있습니다. 마지막 이미지가 최종 결과입니다.
  * 파일은 `mimeType`에 맞는 확장자로 저장하세요.
* **chat completions**: 이미지는 `choices[0].message.content` 텍스트 안에 `data:image/png;base64,...` 같은 데이터 URL로 들어 있습니다. 접두사에서 형식을 읽고 접두사를 떼어 낸 뒤, 길이가 4의 배수가 아니면 `=` 패딩을 붙여 디코딩하세요.
* **이미지 없음**: 네이티브 응답이면 각 후보의 `finishReason`(있으면 `promptFeedback`도)을, chat 응답이면 답변 텍스트를 확인하세요. 안전 차단이나, 모델이 지시에 텍스트로만 답한 경우가 흔한 원인입니다.

## 편집 프롬프트 팁

* 얼굴, 제품 라벨, 레이아웃처럼 그대로 남아야 할 것을 적으세요. 마스크 파라미터가 없으므로 바꿀 영역은 말로 설명합니다.
* "두 번째 이미지의 재킷"처럼 순서와 역할로 각 이미지를 가리키세요.
* 얼굴이나 로고를 그대로 지키려면 자세히 묘사하고 바꾸지 말라고 적으세요.
* 이미지 안에 넣을 텍스트는 정확한 문구를 따옴표로 감싸고 글꼴 스타일을 지정하세요.
* 복잡한 편집은 단계로 나누고, 저장한 결과를 다음 요청의 입력으로 보내세요.

## 오류와 과금

Pro가 받는 값을 보내세요.

| 필드 | 허용 값 | Pro가 받지 않는 값 |
| - | - | - |
| `aspectRatio` | 10종 중 하나 | `1:4`, `4:1`, `1:8`, `8:1` |
| `imageSize` | `1K`, `2K`, `4K`(K는 대문자) | `512` |

* 안전 검사가 출력을 차단한 경우처럼, 이미지 없이 HTTP 200이 반환될 수 있습니다. 편집도 생성과 똑같이 과금되므로 이 호출은 과금됩니다. `finishReason`(있으면 `promptFeedback`도)을 확인하고 지시문이나 참조 이미지를 바꾼 뒤 다시 보내세요. [Nano Banana 개요](https://docs.laozhang.ai/ko/api-capabilities/nano-banana-image.md)의 빈 응답 과금 피하기 절을 참고하세요.
* HTTP 401은 키나 `Authorization: Bearer` 헤더가 잘못되었다는 뜻입니다. Gemini 네이티브 경로는 `x-goog-api-key` 헤더로도 키를 받습니다. 429와 5xx는 백오프를 두고 재시도하고, 타임아웃이 난 요청은 다시 보내기 전에 호출 로그를 확인하세요.
* `fileData` URL을 내려받지 못하면 로그인 없이 열리는지, `robots.txt`가 허용하는지 확인하거나 이미지를 `inlineData`로 보내세요.
* HTTP 413은 요청 본문이 너무 크다는 뜻입니다. 큰 이미지는 URL로 넘기거나, 요청 전체가 20MB 이내가 되도록 줄이세요.
* Base64는 파일 크기를 약 3분의 1 늘리므로, 아주 큰 사진은 인코딩하기 전에 줄이세요.

## 자주 묻는 질문

### `/v1/images/edits`로 편집할 수 있나요?

아니요. Nano Banana Pro 편집은 Gemini 네이티브 `generateContent` 엔드포인트나 OpenAI 호환 `/v1/chat/completions`로 보내며, Images API의 편집 엔드포인트는 쓰지 않습니다.

### 이미지의 한 영역만 편집할 수 있나요?

네, 말로 설명하면 됩니다. 마스크 필드는 없습니다. Google은 이 방식을 시맨틱 마스킹이라고 부르며, 바꿀 요소를 지목하고 나머지는 그대로 두라고 적으면 됩니다.

예: "파란 소파만 갈색 가죽 소파로 바꿔 주세요. 방의 나머지 부분, 배치, 조명은 그대로 유지하세요." 더 많은 팁은 위 편집 프롬프트 팁 절에 있습니다.

### `aspectRatio`를 생략하면 결과는 어떤 모양인가요?

Google의 기본 동작은 출력을 입력 이미지 크기에 맞추는 것이므로, `aspectRatio`를 생략하면 원래 모양이 유지됩니다. 위 로컬 이미지 편집 절의 예제가 이렇게 동작합니다. 다른 모양이 필요할 때만 `aspectRatio`를 지정하고, 1K·2K·4K 선택에는 `imageSize`를 쓰세요.

## 관련 페이지와 출처

* [Nano Banana Pro](https://docs.laozhang.ai/ko/api-capabilities/nano-banana-pro-image.md) — 텍스트→이미지, 종횡비별 출력 크기, Google 검색 그라운딩
* [Nano Banana 2](https://docs.laozhang.ai/ko/api-capabilities/nano-banana2-image.md) — 더 저렴한 4K까지의 생성과 편집
* [Nano Banana 개요](https://docs.laozhang.ai/ko/api-capabilities/nano-banana-image.md) — 5종 모델, 두 요청 형식, 과금 규칙 비교
* [Standard 편집](https://docs.laozhang.ai/ko/api-capabilities/nano-banana-image-edit.md) — `gemini-2.5-flash-image` 편집과 이전 방법
* [호출 로그](https://docs.laozhang.ai/en/faq/call-logs.md) — 요청별 상태와 청구 금액 확인
* [Google: Nano Banana image generation](https://ai.google.dev/gemini-api/docs/image-generation) — 편집 프롬프트, 참조 이미지 제한, 사고
* [Google: generateContent 레퍼런스](https://ai.google.dev/api/generate-content) — `imageConfig` 필드
* [Google: 파일 입력 방법](https://ai.google.dev/gemini-api/docs/file-input-methods) — 인라인 데이터와 공개 URL 입력


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.