대형 이커머스 플랫폼이나 다채널 오픈마켓 셀러 팀에서 대규모 상품을 일괄 등록할 때 가장 큰 병목 현상은 상품 이미지 후가공입니다. 입점 공급사나 제조사에서 제공하는 원본 이미지는 해상도, 화면 비율, 조명 및 배경이 제각각입니다. 데스크톱용 대량 편집 툴은 수동 조작이 필요해 사내 ERP, PIM(상품정보관리), CMS와 엔지니어링 차원에서 직접 연동하기 어렵고, 디자이너에게 수작업을 의존하면 상품 등록에 24~72시간의 지연이 발생하며 SKU당 인건비가 급증합니다.
Cutout.pro는 컴퓨터 비전 기반의 개발자용 REST API를 통해 상품 누끼 제거(배경 투명화), 여백 크롭, 단색 배경 합성 기능을 제공합니다. 이 API를 백엔드의 비동기 이미지 처리 파이프라인에 통합하면, 원본 사진을 수초 만에 아마존, 네이버 스마트스토어, 쿠팡, 쇼피파이 기준에 맞춘 순백색 배경(#FFFFFF), 규격화된 여백, 자연스러운 접지 그림자(Contact Shadow)가 적용된 표준 상품 이미지로 자동 변환할 수 있습니다.
1. Cutout.pro API 규격 및 인증 체계
Cutout.pro의 모든 API는 표준 HTTPS 프로토콜을 통해 호출됩니다. 인증 방식은 간단하며, 모든 요청의 HTTP 헤더에 발급받은 API 키를 전달합니다.
APIKEY: your_cutout_pro_api_key_here
프로덕션 배치 실행 전 잔액 사전 검증
시즌 전환이나 프로모션 시기에는 수만 개의 상품 이미지가 일괄 처리됩니다. 작업 도중 크레딧이 소진되면 에러 코드 4001(크레딧 부족)이 발생하며 대량의 작업이 중단될 수 있습니다. 따라서 파이프라인은 배치 작업을 시작하기 전에 크레딧 잔액을 사전에 확인해야 합니다.
Cutout.pro는 구독 및 잔액 조회를 위한 전용 엔드포인트를 제공합니다.
- 엔드포인트:
GET https://www.cutout.pro/api/v1/mySubscription - 헤더:
APIKEY: <YOUR_API_KEY>,Accept: application/json
응답 JSON 예시:
{
"code": 0,
"data": {
"monthBalance": 1250,
"imageBalance": 5000,
"videoBalance": 0,
"monthStartDate": "2026-10-01 00:00:00",
"monthExpireDate": "2026-11-01 00:00:00"
},
"msg": null,
"time": 1728729600000
}
작업 오케스트레이터에 잔액 사전 검증 단계를 추가하면, 크레딧이 부족할 경우 작업을 안전하게 일시 중지하고 담당자에게 알림을 발송할 수 있습니다.
2. 엔드포인트 모드 선택 및 핵심 파라미터
이커머스 상품 및 사물 배경 제거에는 범용 누끼 모델인 mattingType=6 또는 mattingType=1을 지정합니다. 시스템 아키텍처에 따라 세 가지 호출 모드를 선택할 수 있습니다.
| 모드 | 엔드포인트 | 요청 방식 & Content-Type | 응답 형태 | 추천 아키텍처 환경 |
|---|---|---|---|---|
| 모드 1: 바이너리 스트림 | https://www.cutout.pro/api/v1/matting | POST / multipart/form-data | 바이너리 이미지 스트림 (image/png) | 로컬 디스크 파일 직접 저장 및 메모리 버퍼 처리 |
| 모드 2: Base64 JSON | https://www.cutout.pro/api/v1/matting2 | POST / multipart/form-data | data.imageBase64 포함 JSON | JSON-RPC 기반 마이크로서비스 간 통신 |
| 모드 3: 원격 이미지 URL | https://www.cutout.pro/api/v1/mattingByUrl | GET / 쿼리 파라미터 | data.imageBase64 포함 JSON | 원본 이미지가 S3, Cloudflare R2, CDN에 저장된 경우 |
이커머스 표준화를 위한 필수 요청 파라미터
mattingType(정수, 필수): 상품 및 사물 누끼 작업은6으로 지정.crop(불리언, 선택):true로 설정하면 제품 주변의 빈 투명 여백을 자동으로 잘라내어 바운딩 박스에 밀착시킵니다.cropMargin(문자열, 선택):crop=true일 때 제품 외곽에 추가할 마진."30px"같은 절대 픽셀이나"10%"같은 비율, 상하좌우 개별 지정이 가능합니다.bgcolor(16진수 문자열, 선택): 투명 배경을 단색으로 채웁니다(예: 순백색은FFFFFF,#기호 제외). 특수값'blur'를 넘기면 배경 흐림 효과가 적용됩니다.outputFormat(문자열, 선택): 출력 포맷 지정(png,webp,jpg_<품질>, 예:jpg_85).preview(불리언, 선택):true로 지정 시 해상도가 500x500 픽셀로 제한되며 호출당 0.25 크레딧만 차감됩니다(기본값은 최대 4096x4096px, 15MB 이하 이미지에 대해 1 크레딧 차감). 판매자 등록 시점의 초안 미리보기에 이상적입니다.
3. 대량 배치 처리 및 동시성 제어 (비동기 큐 아키텍처)
Cutout.pro API는 동기식 HTTP 요청으로 동작하여 개별 요청마다 서버 연산이 완료될 때까지 대기합니다. 단, 플랫폼 공식 규정상 **초당 최대 5회(5 QPS)**의 동시성 제한이 엄격히 적용됩니다.
제한 없이 멀티스레드로 동시 요청을 보내면 에러 코드 5005(Too many requests in the queue, please wait)가 대량으로 반환됩니다. 수만 개의 SKU를 안정적으로 처리하려면 메시지 큐를 통한 비동기 트래픽 제어가 필수적입니다.
프로덕션 권장 아키텍처
[ERP / PIM 대량 상품 등록]
│ (SKU 배치 투입)
▼
[메시지 브로커: Redis / RabbitMQ]
│
▼
[Worker 클러스터 (Celery / BullMQ)]
├── 토큰 버킷 속도 제한기 (클러스터 합산 <= 4.5 QPS 제한)
├── Cutout.pro API 호출 (POST /api/v1/matting?mattingType=6)
│ └── 5005 수신 시 지수 백오프 재시도
├── 로컬 이미지 표준화 엔진 (Pillow / Sharp)
│ ├── 정사각형 캔버스 중앙 배치 (2000x2000px)
│ ├── 상품 점유율 85% 리사이즈
│ └── 자연스러운 접지 그림자 (Contact Shadow) 합성
├── 클라우드 오브젝트 스토리지 저장 (AWS S3 / Cloudflare R2)
└── ERP 시스템 Webhook 콜백 (처리 완료 및 이미지 URL 갱신)
안정성 및 예외 처리 정책
- 토큰 버킷 기반 속도 제한: Redis 기반의 토큰 버킷을 두어 전체 워커 풀의 외부 호출 합계가 4.5 QPS를 넘지 않도록 제어합니다.
- 에러 코드별 대응:
5005(큐 포화 / QPS 초과): 지수 백오프(재시도 대기: 1.5초, 3초, 6초 및 지터 추가)를 적용합니다.1002(15MB 초과) 및5008(지원하지 않는 이미지): 데드 레터 큐(DLQ)로 보내고 ERP 관리 화면에 '수동 확인 필요' 플래그를 설정합니다.4001(크레딧 소진): 워커 소비를 즉시 중단하고 긴급 운영 알림을 발송합니다.
4. 이미지 규격화 파이프라인 구현: 규격, 여백 및 그림자 합성
API 파라미터 bgcolor=FFFFFF로 직접 흰색 배경을 채울 수도 있지만, 주요 이커머스 플랫폼의 기준을 충족하려면 추가적인 보정이 필요합니다:
- 캔버스는 엄격한 정사각형이어야 합니다(1:1 비율, 예: 2000x2000px).
- 상품 크기는 캔버스 전체의 80%~85%를 차지해야 일관된 시각적 통일감을 제공합니다.
- 그림자 없는 인위적인 흰색 배경은 상품이 공중에 붕 뜬 듯한 스티커 느낌을 줍니다. 하단에 은은한 접지 그림자를 합성하면 상품의 입체감과 신뢰도가 높아집니다.
가장 효과적인 파이프라인 구조는 Cutout.pro로부터 투명 PNG(crop=true, bgcolor 미지정)를 다운로드받은 후, 로컬 워커에서 그래픽 라이브러리(Python Pillow 또는 Node.js Sharp)를 이용해 규격화 및 그림자 합성을 수행하는 것입니다.
파이썬(Pillow) 기반 파이프라인 구현 예제
import io
import time
import requests
from PIL import Image, ImageFilter
CUTOUT_API_KEY = "YOUR_API_KEY_HERE"
API_URL = "https://www.cutout.pro/api/v1/matting?mattingType=6&crop=true"
def remove_background(image_bytes: bytes, max_retries: int = 3) -> bytes:
"""속도 제한에 대한 지수 백오프가 적용된 Cutout.pro 배경 제거 함수"""
headers = {"APIKEY": CUTOUT_API_KEY}
files = {"file": ("product.jpg", image_bytes, "image/jpeg")}
for attempt in range(max_retries):
response = requests.post(API_URL, headers=headers, files=files, timeout=30)
if response.status_code == 200 and response.headers.get("Content-Type", "").startswith("image/"):
return response.content
try:
err = response.json()
code = err.get("code")
msg = err.get("msg")
if code == 5005: # 큐 포화 상태
time.sleep((2 ** attempt) + 0.5)
continue
elif code == 4001:
raise RuntimeError("Cutout.pro API 크레딧이 소진되었습니다.")
else:
raise ValueError(f"Cutout.pro 처리 실패: {code} - {msg}")
except requests.exceptions.JSONDecodeError:
response.raise_for_status()
raise TimeoutError("Cutout.pro 재시도 횟수를 초과했습니다.")
def standardize_product_image(
transparent_png_bytes: bytes,
target_canvas_size: int = 2000,
fill_ratio: float = 0.85
) -> Image.Image:
"""
정사각형 순백색 캔버스에 이미지를 85% 비율로 배치하고 자연스러운 접지 그림자를 합성합니다.
"""
# 1. 투명 배경의 크롭된 상품 이미지 로드
product = Image.open(io.BytesIO(transparent_png_bytes)).convert("RGBA")
prod_w, prod_h = product.size
# 2. 비율을 유지하며 목표 점유율(85%)에 맞춰 리사이즈
max_dim = int(target_canvas_size * fill_ratio)
scale = min(max_dim / prod_w, max_dim / prod_h)
new_w, new_h = int(prod_w * scale), int(prod_h * scale)
product_resized = product.resize((new_w, new_h), Image.Resampling.LANCZOS)
# 3. 정사각형 순백색 캔버스 생성
canvas = Image.new("RGBA", (target_canvas_size, target_canvas_size), (255, 255, 255, 255))
# 4. 부드러운 접지 그림자(Contact Shadow) 생성
alpha_mask = product_resized.split()[3]
shadow_height = max(10, int(new_h * 0.08))
# 알파 마스크를 수직으로 압축하여 바닥 접지면 형상 제작
shadow_footprint = alpha_mask.resize((new_w, shadow_height), Image.Resampling.BILINEAR)
shadow_footprint = shadow_footprint.filter(ImageFilter.GaussianBlur(radius=15))
# 투명도 35%가 적용된 짙은 회색 그림자 레이어 구축
shadow_layer = Image.new("RGBA", (new_w, shadow_height), (40, 40, 40, 0))
shadow_layer.putalpha(shadow_footprint.point(lambda p: int(p * 0.35)))
# 5. 캔버스 중앙 정렬 및 합성
pos_x = (target_canvas_size - new_w) // 2
pos_y = (target_canvas_size - new_h) // 2
# 그림자를 상품 하단 밑부분에 배치
shadow_y = pos_y + new_h - int(shadow_height * 0.6)
canvas.paste(shadow_layer, (pos_x, shadow_y), shadow_layer)
# 상품 본체 배치
canvas.paste(product_resized, (pos_x, pos_y), product_resized)
# 최종 RGB 이미지 변환
return canvas.convert("RGB")
def process_sku_pipeline(raw_image_path: str, output_path: str):
with open(raw_image_path, "rb") as f:
raw_bytes = f.read()
# 1단계: 원격 API 누끼 제거
cutout_bytes = remove_background(raw_bytes)
# 2단계: 로컬 캔버스 규격화 및 그림자 합성
final_image = standardize_product_image(cutout_bytes)
# 3단계: 최적화된 JPEG 파일 저장
final_image.save(output_path, "JPEG", quality=90, optimize=True)
5. 실무 권장 사항 및 비용 최적화
mattingByUrl을 활용한 대역폭 절감: 원본 이미지가 이미 S3나 CDN에 저장되어 있다면 파일 업로드 대신mattingByUrl엔드포인트를 호출하십시오. 서버의 업로드 대역폭을 절약하고 전송 지연을 크게 줄일 수 있습니다.- 2단계 퀄리티 분기 전략: 셀러 등록이나 입점 초안 검수 단계에서는
preview=true(0.25 크레딧)를 적용하고, 상품이 승인되어 정식 게시될 때만 고해상도(1 크레딧) 호출을 실행하여 크레딧 낭비를 방지합니다. - 투명 PNG 원본 아카이빙: Cutout.pro에서 반환받은 투명 PNG 파일은 콜드 스토리지에 보관하십시오. 추후 플랫폼 가이드라인이 변경되어 배경색을 옅은 회색으로 바꾸거나 여백 비율을 조정해야 할 때, 유료 API를 다시 호출하지 않고 로컬 스크립트만으로 전체 카탈로그를 무료로 재생성할 수 있습니다.