> [Site index](https://perfectvector.com/llms.txt) — available pages and descriptions.

# Python에서 이미지 벡터화 API로 SVG 변환하기

> Python으로 PNG, JPEG, WebP를 벡터화 API에 보내 SVG를 저장합니다. 테스트 응답을 확인하고 연결이 끊겨도 기존 변환을 이어가는 방법을 살펴봅니다.

Source: https://perfectvector.com/ko/blog/vectorize-image-python-api

Language: ko
Author: Jay
Published: 2026-11-09T08:00:00+09:00

Python 스크립트로 래스터 이미지를 PerfectVector 벡터화 API에 보내고 원본 옆에 SVG를 저장할 수 있습니다. 아래 예제는 파일을 받기 전에 변환 ID부터 출력합니다. 연결이 끊기면 그 ID로 상태를 확인하거나, 미리 정해 둔 요청 키로 같은 변환을 다시 조회할 수 있습니다.

## 테스트 키와 이미지 한 장 준비하기

[Developer API 페이지](https://perfectvector.com/account/developers)에서 테스트 키를 만드세요. 터미널 환경 변수 `PERFECTVECTOR_API_KEY`에 설정하고, 스크립트나 버전 관리에는 넣지 마세요. 프로젝트의 Python 환경에서 `python -m pip install requests`로 Requests를 설치합니다.

처음에는 `logo.png` 같은 512 × 512 로고를 사용해 보세요. API는 최대 5 MiB의 단일 프레임 PNG, JPEG, WebP를 받으며, 가로와 세로는 각각 100\~4096픽셀이어야 합니다. 테스트 모드는 업로드를 검사한 뒤 “TEST MODE”가 표시된 고정 SVG를 무료로 반환합니다. 이 파일로 요청과 다운로드를 확인하고, 실제 이미지의 벡터화 품질은 실사용 모드에서 평가하세요. [PerfectVector API 테스트 모드](https://perfectvector.com/docs/api/test-mode)

테스트 키로 아래 Python 스크립트를 실행해 SVG가 정상적으로 파싱되는지 확인했습니다. 같은 요청 키로 동일한 파일을 다시 보내자 두 번 모두 같은 변환 ID가 반환됐습니다.

**작업 흐름**

![로컬 래스터 파일이 요청 키와 함께 클라우드로 전송되고 벡터 파일로 돌아와 디스크에 저장되는 흐름.](https://perfectvector.com/blog/vectorize-image-python-api/workflow.webp)

*요청 키를 업로드 정보와 함께 보관하고, SVG를 다운로드하기 전에 변환 ID를 저장하세요.*

## Python으로 이미지를 보내고 SVG 저장하기

아래 코드를 `vectorize.py`로 저장하세요. Requests의 `files` 인자는 원본 바이트를 `image` 폼 필드에 넣어 멀티파트 요청을 만듭니다. [Requests 멀티파트 업로드](https://requests.readthedocs.io/en/latest/user/quickstart/#post-a-multipart-encoded-file)

```python
import os
import sys
import time
from pathlib import Path

import requests

API = "https://api.perfectvector.com/v1"
AUTH = {"Authorization": f"Bearer {os.environ['PERFECTVECTOR_API_KEY']}"}


def checked(response):
    content_type = response.headers.get("Content-Type", "").split(";")[0]
    if response.status_code >= 400 and content_type == "application/problem+json":
        problem = response.json()
        raise RuntimeError(f"{problem['code']} (request {problem['request_id']})")
    response.raise_for_status()
    return response


def vectorize(source, destination, operation_id):
    with source.open("rb") as image:
        response = checked(requests.post(
            f"{API}/vectorizations",
            headers={**AUTH, "Idempotency-Key": operation_id, "Prefer": "wait=10"},
            files={"image": (source.name, image)},
            timeout=30,
        ))

    conversion = response.json()
    conversion_id = conversion["id"]
    print(f"Conversion ID: {conversion_id}", flush=True)
    deadline = time.monotonic() + 720
    while conversion["status"] in {"queued", "processing"}:
        if time.monotonic() >= deadline:
            raise TimeoutError(f"Stopped polling {conversion_id}")
        time.sleep(2)
        conversion = checked(requests.get(
            f"{API}/vectorizations/{conversion_id}", headers=AUTH, timeout=30,
        )).json()

    if conversion["status"] != "succeeded":
        error = conversion["results"][0].get("error") or {}
        raise RuntimeError(f"{conversion_id}: {error.get('code', conversion['status'])}")

    svg = checked(requests.get(
        f"{API}/vectorizations/{conversion_id}/result", headers=AUTH, timeout=30,
    ))
    if svg.headers.get("Content-Type", "").split(";")[0] != "image/svg+xml":
        raise ValueError("Expected an SVG response")
    partial = destination.with_suffix(".svg.part")
    partial.write_bytes(svg.content)
    partial.replace(destination)
    print(f"{destination} saved ({len(svg.content)} bytes)")


if __name__ == "__main__":
    source = Path(sys.argv[1])
    if source.suffix.lower() not in {".png", ".jpg", ".jpeg", ".webp"}:
        raise SystemExit("Choose a PNG, JPEG or WebP file")
    if source.stat().st_size > 5 * 1024 * 1024:
        raise SystemExit("Choose a file no larger than 5 MiB")
    vectorize(source, source.with_suffix(".svg"), sys.argv[2])
```

`logo.png`가 있는 폴더에서 실행하세요. 실행 전에 이 변환에 사용할 ID를 정하고 기록해 둡니다. API에서 *멱등성 키*라고 부르는 값으로, 같은 업로드를 다시 보내도 하나의 변환으로 처리할 수 있습니다. 예제에서는 `logo-asset-0001`을 사용합니다. 다른 이미지나 작업에는 새 키를 쓰세요. [PerfectVector 안전한 재시도](https://perfectvector.com/docs/api/idempotency)

```bash
python vectorize.py logo.png logo-asset-0001
```

테스트가 성공하면 변환 ID와 파일 크기(바이트)가 출력되고 `logo.png` 옆에 `logo.svg`가 생깁니다. `logo.svg`를 열어 샘플이 제대로 표시되는지 확인하세요. 스크립트는 다운로드가 끝나면 같은 이름의 기존 SVG를 덮어쓰므로 첫 실행은 임시 폴더에서 하는 편이 좋습니다.

스크립트는 완료되지 않은 변환을 반환하기 전 최대 10초 기다리도록 서버에 요청합니다. `queued`와 `processing` 상태에서는 약 2초 간격으로 상태를 확인하고, `succeeded`일 때만 다운로드합니다. 테스트 변환은 즉시 끝납니다. 실사용 환경에 적용하기 전, 완료되지 않은 상태의 응답을 로컬 테스트 데이터로 만들어 상태 확인 로직을 검증하세요. [PerfectVector 대기와 비동기 처리](https://perfectvector.com/docs/api/waiting-and-async)

## 시간 초과 후 기존 변환 이어가기

Python에서 이미 변환 ID를 출력했다면 `GET /v1/vectorizations/{id}`로 상태를 확인하세요. 성공하면 같은 계정과 키 모드로 `GET /v1/vectorizations/{id}/result`를 호출해 SVG를 받습니다. 결과 링크는 변환이 끝난 뒤 24시간 후 만료되므로 나중에도 필요한 파일은 직접 보관하세요. [PerfectVector 결과 다운로드](https://perfectvector.com/docs/api/results)

ID가 출력되기 전에 Python이 멈췄다면 첫 요청부터 24시간 안에 같은 파일 바이트와 같은 멱등성 키로 명령을 다시 실행하세요. 첫 업로드가 접수됐다면 API가 기존 변환을 반환합니다. 이 시간이 지나면 같은 키로 제출해도 새 변환이 시작될 수 있습니다. [PerfectVector 안전한 재시도](https://perfectvector.com/docs/api/idempotency)

| 메시지                                                 | 확인할 사항                                                            |
| --------------------------------------------------- | ----------------------------------------------------------------- |
| `401 invalid_api_key`                               | Python이 실행되는 환경에 유효한 테스트 키를 설정하세요. 이전 키를 폐기했다면 같은 모드에서 새 키를 만드세요. |
| `415 unsupported_media_type` 또는 `422 invalid_image` | 원본의 실제 형식과 픽셀 크기를 확인하세요. 파일을 수정했다면 새 키로 업로드하세요.                   |
| 변환 ID 뒤에 `processing_failed`                        | 변환 레코드는 만들어졌지만 이미지를 벡터화하지 못했습니다. 원본을 살펴보고 수정한 파일로 새 작업을 시작하세요.    |
| `409 idempotency_conflict`                          | 같은 키로 다른 이미지 바이트나 옵션을 보냈습니다. 원본과 기존 옵션으로 복구하거나, 새 입력에 새 키를 쓰세요.   |

지원팀에 문의할 때는 예외에 표시된 요청 ID나 스크립트가 출력한 변환 ID를 보관하세요. [API 오류 문서](https://perfectvector.com/docs/api/errors)에서 안전하게 재시도할 수 있는 오류를 확인할 수 있습니다.

## 자주 묻는 질문

### 같은 Python 스크립트로 JPEG나 WebP도 벡터화할 수 있나요?

네. 첫 번째 인자로 JPEG 또는 WebP 파일을 넘기세요. 크기, 가로·세로 길이, 단일 프레임 조건이 동일하게 적용되며 출력 확장자는 SVG입니다.

### 이 Python 예제를 폴더 전체에 적용할 수 있나요?

먼저 한 파일로 업로드와 다운로드를 확인하세요. 폴더를 처리하려면 파일마다 요청 키, 변환 ID, 출력 경로를 재시작 후에도 남는 큐에 기록하세요. PerfectVector의 기본 설정은 계정당 실사용 변환을 한 번에 하나만 허용하므로, 현재 변환이 끝난 뒤 다음 파일을 제출하세요. [PerfectVector API 제한](https://perfectvector.com/docs/api/limits)

## 출처

1. [Requests — 빠른 시작](https://requests.readthedocs.io/en/latest/user/quickstart/) — 멀티파트 파일, 시간 제한, 응답 바이트.
2. [PerfectVector — 테스트 모드](https://perfectvector.com/docs/api/test-mode) — 업로드 제한, 고정 테스트 SVG, 테스트 크레딧 처리.
3. [PerfectVector — 대기와 비동기 처리](https://perfectvector.com/docs/api/waiting-and-async) — 서버 대기 설정, 상태 확인, 테스트 요청 완료 시점.
4. [PerfectVector — 멱등성](https://perfectvector.com/docs/api/idempotency) — 키 유효 시간과 범위, 충돌 및 재요청 규칙.
5. [PerfectVector — 결과](https://perfectvector.com/docs/api/results) — 결과 엔드포인트, 인증, 만료.
6. [PerfectVector — 오류](https://perfectvector.com/docs/api/errors) — HTTP 오류 코드와 복구 방법.
7. [PerfectVector — 제한](https://perfectvector.com/docs/api/limits) — 기본 동시 변환 한도와 파일 제한.

***

[PerfectVector API 페이지에서 테스트 키를 발급받고](https://perfectvector.com/ko/api) 직접 준비한 이미지로 스크립트를 실행해 보세요. 저장한 SVG가 열리고 터미널에 변환 ID가 출력되는지 확인하세요.

## Explore

- [Read the HTML article](https://perfectvector.com/ko/blog/vectorize-image-python-api)
- [2026 최고의 AI 이미지 벡터화 도구: 용도별 추천](https://perfectvector.com/ko/blog/best-ai-vectorizers-2026.md)
- [Claude Code와 MCP로 폴더의 이미지를 SVG로 일괄 변환하기](https://perfectvector.com/ko/blog/batch-vectorize-images-claude-code-mcp.md)
- [Product facts](https://perfectvector.com/product-facts.md)
- [FAQ](https://perfectvector.com/faq.md)
- [Pricing and credits](https://perfectvector.com/pricing.md)
