GPT-6 Sol·Claude Opus 5.5 출시GPT-6 Sol 요금은 5.6 Sol의 절반

GPT Image 2.5 API: Python으로 이미지 생성하고 편집하기

POST 한 번이면 작업이 만들어지고, GET 한 번이면 결과를 읽습니다. 실행한 요청 코드와 2026년 10월 29일에 시험한 크기, 편집 전후 비교를 담았습니다.

Kiki, OmniaKey COO약 7분
이 페이지 목차

https://api.omniakey.com/v1/media/tasks 로 POST를 한 번 보내고 model에 gpt-image-2.5-flare 를 넣은 뒤, 돌아온 작업 id를 계속 조회하고 status가 succeeded 가 되면 assets[0].url 을 내려받습니다. 2026년 10월 29일에 1K, 2K, 1536x1024로 이미지를 만들고 카페 사진 한 장을 편집했습니다. 파일을 모두 열어 실제 픽셀 크기를 읽었더니 1024×1024, 2048×2048, 1536×1024, 1024×682였습니다. 1K 생성은 29.5초, 2K 생성은 45.2초가 걸렸습니다.

2.5 모델 id는 무엇을 써야 하나

gpt-image-2.5-flare 를 쓰면 됩니다. 아래 모든 실행에서 호출한 id입니다. GPT-Image 2.5 Flare 모델 페이지(2026년 10월 29일 확인)에는 제공사가 OpenAI라고 적혀 있고, 텍스트에서 이미지 생성과 이미지 편집을 지원하며, "Guide updated 2026-10-27"이라는 안내가 붙어 있습니다. 같은 페이지에 두 번째 2.5 id인 gpt-image-2.5-sunburst 도 있습니다.

Flare는 두 작업을 모두 처리합니다. 생성은 프롬프트만 보내고, 편집은 프롬프트와 원본 이미지 한 장을 함께 보냅니다. 품질은 low, medium, high 세 단계이고 같은 페이지에 단계가 가격을 바꾸지 않는다고 적혀 있습니다. 여기서는 모든 실행이 medium이었습니다. sunburst, low와 high, 4K와 3840x2160, 마스크, 여러 장의 참조 이미지는 시험하지 않았으니, 우선 Flare와 medium, 원본 이미지 한 장 구성으로 계획을 세우고 나머지는 직접 시험한 뒤에 정하시기 바랍니다.

요청 코드

아래 스크립트는 실제로 실행한 것이며 한 줄도 바꾸지 않았습니다. 도우미 함수 두 개, 그다음에 생성 호출 한 번과 편집 호출 한 번이 이어집니다. Python 표준 라이브러리만 사용하고, 키는 OMNIAKEY_API_KEY 에서 읽고, 각 PNG는 스크립트를 실행한 폴더에 저장합니다.

python
import base64
import json
import os
import time
import urllib.request
import uuid

API = "https://api.omniakey.com/v1/media/tasks"
KEY = os.environ["OMNIAKEY_API_KEY"]
MODEL = "gpt-image-2.5-flare"

def request(method, url, body=None, extra_headers=None):
    headers = {"Authorization": f"Bearer {KEY}", "User-Agent": "omniakey-example/1"}
    data = None
    if body is not None:
        headers["Content-Type"] = "application/json"
        data = json.dumps(body).encode()
    headers.update(extra_headers or {})
    req = urllib.request.Request(url, data=data, headers=headers, method=method)
    with urllib.request.urlopen(req, timeout=120) as resp:
        return json.load(resp)

def run_task(body, out_path):
    task = request("POST", API, body, {"Idempotency-Key": str(uuid.uuid4())})["id"]
    for _ in range(150):
        time.sleep(4)
        state = request("GET", f"{API}/{task}")
        if state["status"] not in ("queued", "processing"):
            break
    if state["status"] != "succeeded":
        raise RuntimeError(state.get("error") or state["status"])
    asset_url = state["assets"][0]["url"]  # 서명된 링크: 약 1시간만 유효하므로 바로 내려받는다
    req = urllib.request.Request(asset_url, headers={"User-Agent": "omniakey-example/1"})
    with urllib.request.urlopen(req, timeout=120) as resp, open(out_path, "wb") as f:
        f.write(resp.read())
    return task

def generate_image(prompt, out_path, size="1K", quality="medium"):
    body = {
        "model": MODEL,
        "type": "image",
        "operation": "generate",
        "input": {"prompt": prompt},
        "parameters": {"size": size, "quality": quality},
    }
    return run_task(body, out_path)

def edit_image(source_path, prompt, out_path, size="1K", quality="medium"):
    with open(source_path, "rb") as f:
        image = base64.b64encode(f.read()).decode()
    body = {
        "model": MODEL,
        "type": "image",
        "operation": "edit",
        "input": {"prompt": prompt, "image": {"data": image, "mime_type": "image/jpeg"}},
        "parameters": {"size": size, "quality": quality},
    }
    return run_task(body, out_path)

if __name__ == "__main__":
    task = generate_image(
        "A small glass greenhouse on a hillside at sunrise, morning fog in the valley, "
        "soft watercolor style, a wooden bench outside the door, no people, no text.",
        "greenhouse.png",
    )
    print("generate task", task)
    task = edit_image(
        "cafe-base.jpg",
        "Change the red bicycle to matte black. Keep everything else exactly the same: "
        "the table, the cup, the window frame and the daylight. Photorealistic, no text, no logos.",
        "cafe-edited.png",
    )
    print("edit task", task)

Authorization: Bearer <key> 는 모든 호출에 붙습니다. 생성 호출에는 Idempotency-Key 도 필요한데, 스크립트는 새 UUID를 넣습니다. 본문에는 type을 "image"로, operation을 "generate" 또는 "edit"로 두고, 프롬프트는 input.prompt 에, 크기와 품질은 parameters 에 넣습니다. API는 n 도 받지만 유효한 값은 1뿐이라 스크립트에서는 생략했습니다. 생성 호출은 HTTP 202와 작업 id를 돌려주고, status는 queued 에서 시작합니다. 루프는 4초마다 상태를 확인하고, 작업 중인 두 상태를 벗어날 때까지 기다립니다.

편집은 JPEG를 input.image 에 인라인 Base64 객체로 넣고 MIME 타입을 함께 적습니다. 요청 본문은 Base64를 포함해 1 MiB까지이므로, 스크립트는 약 230 KB인 1024픽셀 JPEG를 보냅니다.

시험한 크기와 돌아온 결과

실행은 네 번, 모두 품질 medium, 날짜는 2026년 10월 29일입니다. 세 번은 요청한 크기로 돌아왔습니다. 1K 편집만 두 번 중 한 번은 다른 크기였습니다.

  • 1K, 생성 — 파일에서 읽은 픽셀: 1024×1024; 날짜: 2026년 10월 29일
  • 2K, 생성 — 파일에서 읽은 픽셀: 2048×2048; 날짜: 2026년 10월 29일
  • 1536x1024, 생성 — 파일에서 읽은 픽셀: 1536×1024; 날짜: 2026년 10월 29일
  • 1K, 편집 — 파일에서 읽은 픽셀: 1024×682; 날짜: 2026년 10월 29일

아래 온실은 위 코드와 같은 요청 본문으로 만든 1K 생성 이미지입니다.

일출 무렵 언덕 위에 선 수채화풍 유리 온실. 계곡에는 아침 안개가 끼어 있고 문 밖에 나무 벤치가 있다.
2026년 10월 29일 GPT-Image 2.5 Flare로 OmniaKey API를 통해 생성. 크기 1K, 품질 medium.

목록에서 챙길 점은 두 가지입니다. 첫째, 크기는 내려받은 파일에서 읽어야 합니다. 1K 편집은 정사각형을 요청했는데 1024×682로 돌아왔고, 그 비율은 보낸 1024×683 JPEG와 같았습니다. 같은 편집을 1K로 한 번 더 실행하니 이번에는 1024×1024였습니다. 둘째, 이미지 API 문서(2026년 10월 29일 확인)의 크기 목록에는 auto, 1K, 2K, 4K, 3840x2160이 있고 목록에 없는 크기는 과금 전에 거절한다고 적혀 있는데, 2026년 10월 29일의 1536x1024 호출은 거절되지 않고 1536×1024를 돌려주었습니다. 한 가지 크기를 전제로 화면을 설계하기 전에 실제 파일을 확인하십시오.

편집은 장면을 두고 한 곳만 바꾼다

편집에서 답해야 할 것은 두 가지입니다. 무엇이 바뀌는지, 무엇이 남는지입니다. 여기서는 변경을 하나만 요청하고 남아야 할 것들을 하나씩 짚었습니다.

프롬프트: "Change the red bicycle to matte black. Keep everything else exactly the same: the table, the cup, the window frame and the daylight. Photorealistic, no text, no logos."

왼쪽: 카페 창밖에 세워 둔 빨간 자전거. 오른쪽: 같은 창을 편집한 뒤 자전거가 어두운 색이 된 모습.
왼쪽: 보낸 원본 사진. 오른쪽: 2026년 10월 29일 편집 한 번의 출력. 크기 1K, 품질 medium. 자전거만 바꿔 달라고 했고 테이블, 컵, 화분은 그대로 남아 있습니다.

자전거는 어두운 색으로 돌아왔고 테이블, 컵, 화분, 창틀은 화면에 그대로 있었습니다. 원본은 1024×683 JPEG였고 출력은 1024×682였으며 실행에는 38.0초가 걸렸습니다. 남길 것 목록은 매번 적으십시오. 프롬프트 구조 전반은 GPT Image 2 프롬프트 가이드에서 다룹니다.

오류와 제한

픽셀이 생기기 전에 결과를 좌우하는 것은 헤더 두 개입니다. Bearer 토큰과 고유한 Idempotency-Key 입니다. 이 둘만 맞으면 나머지 호출은 재시도하기 쉽습니다.

보내는 내용돌아오는 응답
키 없이 생성 호출400 missing_idempotency_key
같은 키, 같은 본문으로 두 번200과 기존 작업. 새로 과금되지 않음
같은 키, 바뀐 본문409 idempotency_key_reused

키는 최대 255자입니다(2026년 10월 29일 확인한 문서 기준). 같은 본문으로 다시 보내는 것이 안전한 재시도입니다. 기존 작업이 돌아오고 새로 과금되지 않습니다. 본문은 Base64를 포함해 1 MiB 아래로 유지하십시오. 원본 이미지는 보내기 전에 줄이거나 압축하십시오.

작업이 성공하면 assets[0].url 은 서명된 링크가 되며, 문서에 따르면 약 1시간 유효합니다. 바로 내려받거나 같은 작업을 다시 조회해 새 링크를 받으십시오. 작업 기록은 24시간 보관됩니다.

2026년 10월 29일에 헤더 하나가 발목을 잡았습니다. Python urllib의 기본 User-Agent로 POST를 보내면 Cloudflare가 HTTP 403과 본문 "error code: 1010"을 돌려주었습니다. 같은 POST를 직접 넣은 User-Agent: omniakey-example/1 헤더와 함께 보내면 API에 도달했고, 빈 본문에 대해 400 invalid_request 를 돌려주었으며 과금은 없었습니다. 문서에는 Authorization과 Idempotency-Key만 적혀 있으니 클라이언트에서 User-Agent를 직접 설정하십시오.

API 작업에는 GPT Image 2.5와 GPT Image 2 중 무엇인가

시험한 2.5 id는 Flare입니다. GPT Image 2의 id는 GPT Image 2 모델 페이지에 있는 것처럼 gpt-image-2 입니다. 그 id로 필요한 결과가 나오는 스크립트라면 바꿀 이유가 없습니다.

장면을 유지한 채 물체 하나만 바꾸는 사진에는 Flare와 medium 조합이 2026년 10월 29일 실행으로 확인한 범위입니다. 생성 세 가지 크기와 1024×682 편집이 여기에 해당합니다. GPT Image 2.5 vs GPT Image 2 비교에 두 모델의 크기와 같은 프롬프트 결과가 있으니 숫자를 보면서 고르십시오. 현재 요금은 요금 페이지에 있습니다.

자주 묻는 질문

gpt-image-2.5-flare와 gpt-image-2.5-sunburst 중 무엇을 써야 하나?

위의 모든 실행은 Flare였고, 편집에서 남겨 달라고 한 장면이 그대로 남았습니다. 모델 페이지에는 두 번째 2.5 id로 Sunburst가 있습니다. Flare로 시작하고, 가장 어려운 편집을 Sunburst에서도 통과시킨 뒤에 바꾸십시오.

1536x1024 같은 가로 크기를 요청할 수 있나?

2026년 10월 29일의 1536x1024 생성은 1536×1024로 돌아왔습니다. 이미지 API 문서의 크기 목록에는 이 모델에서 그 값이 없으니, 운영에 쓰기 전에 파일을 읽고 문서도 확인하십시오.

편집 결과가 요청한 크기와 다른 이유는 무엇인가?

같은 1K 편집이 한 번은 1024×682, 다른 한 번은 1024×1024로 돌아왔습니다. 요청한 크기는 약속이 아니라 요청으로 보십시오. 배치하기 전에 PNG를 열어 너비와 높이를 읽으십시오.

User-Agent 헤더가 꼭 필요한가?

2026년 10월 29일에 Python 기본 User-Agent로 보낸 요청은 HTTP 403과 Cloudflare 오류 1010을 받았습니다. 직접 넣은 User-Agent 헤더를 붙인 같은 요청은 API에 도달했으니, 헤더를 넣어 보내십시오.

이미지 링크는 얼마나 유효한가?

문서에 따르면 서명된 링크는 약 1시간 유효합니다. 새 링크가 필요하면 작업을 다시 조회하고, 작업이 성공하면 바로 파일을 내려받으십시오.

이 글에서 다루는 모델

GPT Image 2.5이미지 APIPython이미지 편집API

관련 글

최근 글