튜토리얼
hiapi API에서 recraft-v4-styles-pro/text-to-image를 호출하는 방법: curl과 Python
이 엔드포인트가 하는 일과 사용 시점
recraft-v4-styles-pro/text-to-image는 텍스트 프롬프트를 이미지로 변환하며, 두드러진 특징은 스타일 인지입니다. 프롬프트의 문구에만 의존하지 않고 스타일 참조를 통해 결과의 시각적 언어를 유도할 수 있습니다. 출력이 한두 번의 생성에서만 좋아 보이는 것이 아니라 대량 생성 전반에 걸쳐 일관된 느낌을 유지해야 할 때 실용적인 선택입니다.
개발자는 주로 다음 시나리오에서 이를 사용합니다:
- 브랜드 일관성 소재—키 비주얼, 소셜 카드, 광고 변형이 모두 동일한 시각 체계 안에 속해야 합니다.
- 제품 및 마케팅 목업—프롬프트를 반복 조정하고 스타일을 고정하여 브랜드에 맞는 변형 세트를 만들어냅니다.
- 파이프라인 단계—생성이 더 큰 자동화의 한 단계로 작동하며, 다른 서비스가 저장된 이미지를 소비합니다.
아래의 모든 코드 예제 작성 방식을 결정하는 한 가지 특성이 있습니다: 이미지 생성이 비동기라는 점입니다. 요청이 작업을 제출한 뒤 즉시 반환되며, 이미지는 나중에 나타납니다. 제출 단계와 폴링 단계를 작성하고 이를 두 개의 독립적인 관심사로 취급해야 합니다.
hiapi 자격 증명 및 요청 기반 준비
모든 호출은 hiapi의 통합 엔드포인트 인터페이스를 거치므로, 첫 요청 전에 세 가지를 준비해야 합니다:
- API 키, hiapi 계정에서 발급받습니다. 다른 비밀 정보처럼 취급하세요: 환경 변수에서 로드하고, 공유할 수 있는 스크립트에 절대 하드코딩하지 마세요.
- 모델 식별자, 게시된 것과 정확히 일치해야 합니다:
recraft-v4-styles-pro/text-to-image. - HTTP를 지원하는 도구—탐색용
curl, 그리고 모든 지속화 시나리오용 HTTP 라이브러리.
export HIAPI_API_KEY="your-key-here"
일찍 내면화할 가치가 있는 규칙:
- JSON 요청 본문을 보낼 때
Content-Type: application/json을 사용하세요. - bearer token 헤더로 인증하세요.
- 모델 id, 프롬프트, 스타일 참조를 페이로드의 각각 독립된 필드로 두고, 모든 것을 하나의 문자열에 밀어넣지 마세요—그렇게 해야 폴링 단계와 로그가 더 이해하기 쉬워집니다.
정확한 요청 헤더 이름, 기본 URL, 현재 필드 정의는 이 모델의 hiapi API 참조 문서를 확인하세요. 이 튜토리얼은 호출의 형태로, 참조 문서는 이름의 권위 있는 출처로 간주하세요.
작동하는 curl 요청 하나
다음은 제출 호출입니다. 전송, 인증, 요청 본문의 세 계층으로 이해하세요.
curl -sS -X POST "$HIAPI_BASE_URL/generate" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "recraft-v4-styles-pro/text-to-image",
"prompt": "minimalist product photo of a ceramic mug on a linen surface, soft daylight",
"style_references": []
}'
줄별 설명:
-X POST—가져오기가 아닌 작업 제출.Authorization: Bearer ...—토큰은 환경 변수에서 오므로 이 명령은 터미널에 안전하게 붙여넣을 수 있고, 변수를 제거하면 안전하게 공유할 수도 있습니다.-d '{...}'—JSON 요청 본문.model은 정확한 식별자입니다.prompt는 장면을 설명하는 자유 텍스트입니다.style_references는 스타일 제어의 연결 지점이며 다음에 논의합니다.-sS—진행 표시줄은 조용히 하지만 오류는 여전히 표시하므로 실패한 호출이 보입니다.
성공적인 응답은 이미지가 아닌 확인입니다: 작업의 식별자와 상태를 받습니다. 해당 식별자를 기록하세요—폴링에 필요한 유일한 핸들입니다. 대화식으로 탐색 중이라면 응답을 JSON 포매터로 처리하여 작업 id와 상태를 더 눈에 띄게 만드세요.
프롬프트와 함께 스타일 참조 전달하기
멘탈 모델은 간단합니다: 프롬프트는 무엇을, 스타일 참조는 어떻게 보여야 하는지를 설명합니다. 페이로드에서 이를 분리해 두면 유연성을 유지할 수 있습니다—동일한 프롬프트로 여러 스타일 세트에 대해 재실행하여 결과를 비교할 수 있습니다.
{
"model": "recraft-v4-styles-pro/text-to-image",
"prompt": "ceramic mug on a linen surface, soft daylight",
"style_references": [
"https://your-bucket.example.com/styles/mug-ref-01.jpg",
"https://your-bucket.example.com/styles/mug-ref-02.jpg"
]
}
실용적 조언:
- 참조 없이 시작하세요. 먼저 프롬프트만으로 실행하세요. 그다음 참조 하나를 추가하고 차이를 관찰한 후 두 개를 더하세요. 한 번에 하나만 변경하는 것이 처음부터 전체 스타일 세트를 사용하는 것보다 훨씬 많은 정보를 줍니다.
- 참조를 접근 가능하게 유지하세요. 서비스가 안정적으로 가져올 수 있는 곳—공개 버킷이나 충분한 유효 기간이 있는 서명 URL—에 호스팅하고, 몇 분 후 만료되는 링크는 피하세요.
- 세트를 조화롭게 유지하세요. 서로 일관된 참조(유사한 조명, 색상 팔레트, 질감)가 모순을 조정해야 하는 뒤섞인 잔뜩보다 더 안정적인 결과를 만들어내는 경향이 있습니다.
- 참조를 버전 관리하세요. 안정적인 키 아래에 저장하세요. 다음 달에 출력에 문제가 생기면 그때 어떤 참조 파일이 사용되었는지 정확히 알아야 합니다.
이 모델의 hiapi 참조 문서를 확인하여 스타일 참조가 URL, 업로드한 리소스, 또는 명명된 프리셋의 형태로 전달되는지, 그리고 그 수와 형식에 어떤 제한이 있는지 확인하세요.
Python에서의 동일한 호출
curl 호출은 직접 변환됩니다. 작은 함수로 감싸면 파이프라인 단계로 재사용할 수 있습니다.
import os
import requests
HIAPI_BASE_URL = os.environ["HIAPI_BASE_URL"]
HIAPI_API_KEY = os.environ["HIAPI_API_KEY"]
def submit_generation(prompt: str, style_references: list[str] | None = None) -> str:
"""텍스트-이미지 작업을 제출하고 작업 id를 반환합니다."""
payload = {
"model": "recraft-v4-styles-pro/text-to-image",
"prompt": prompt,
"style_references": style_references or [],
}
response = requests.post(
f"{HIAPI_BASE_URL}/generate",
headers={
"Authorization": f"Bearer {HIAPI_API_KEY}",
"Content-Type": "application/json",
},
json=payload,
timeout=30,
)
response.raise_for_status()
data = response.json()
return data["job_id"]
설계 설명:
- 항상 타임아웃을 설정하세요. 무한히 매달린 제출은 충돌처럼 워커 프로세스를 효과적으로 차단합니다.
raise_for_status()는 비 2xx 응답을 포착하고 로깅할 수 있는 예외로 변환하며, 잘못된 형식의 응답 본문을 가지고 조용히 계속하지 않습니다.- id만 반환하세요. 작업 id는 제출과 폴링 사이의 계약입니다. 응답의 나머지 부분을 호출 코드 외부에 두면 다음 섹션이 더 쉽게 작성됩니다.
hiapi 참조 문서에서 실제 응답 필드 이름을 확인하고 data["job_id"]를 그에 맞게 조정하세요—필드 명명이 이 문서의 예제와 가장 다를 가능성이 높은 부분입니다.
작업 완료 상태 폴링하기
생성에는 시간이 걸립니다. 고정 간격으로 폴링하고, 종료 상태에서 멈추고, 최종적으로 포기하세요.
import time
def wait_for_job(job_id: str, timeout: float = 300, interval: float = 3) -> dict:
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
response = requests.get(
f"{HIAPI_BASE_URL}/jobs/{job_id}",
headers={"Authorization": f"Bearer {HIAPI_API_KEY}"},
timeout=30,
)
response.raise_for_status()
job = response.json()
status = job["status"]
if status == "succeeded":
return job
if status == "failed":
raise RuntimeError(f"Job {job_id} failed: {job.get('error')}")
time.sleep(interval)
raise TimeoutError(f"Job {job_id} did not finish within {timeout}s")
덜 명확한 부분:
- 두 가지가 아닌 세 가지 결과. 대기 중, 성공, 실패. 인식되지 않은 상태는 대기 중으로 취급하고 로그 한 줄을 남기세요—그러면 새로 추가된 상태가 워커 프로세스를 충돌시키지 않습니다.
- 전체 대기에 하나의 데드라인을 사용하세요.
time.monotonic()데드라인은 시계 조정에 영향받지 않지만, 벽시계 시간 계산은 그렇지 않습니다. - 너무 자주 요청하지 마세요. 이미지 생성의 경우 각 확인 사이에 몇 초면 충분합니다. 더 빠르게 폴링해야 한다면 간격을 줄이지 말고 시도 사이에 백오프하세요.
- 타임아웃을 강제하세요. 영원히 끝나지 않는 작업은 컨테이너가 죽을 때까지 실행되는 루프가 아니라 알림 가능한 오류로 나타나야 합니다.
대량의 작업을 실행한다면 개별 작업마다 빡빡한 루프에서 폴러를 생성하는 대신, 이벤트 루프나 스레드 풀을 사용하고 간격을 엇갈리게 하여 일괄 제출하고 동시에 폴링하세요.
출력 다운로드 및 저장
완료된 작업은 이미지 참조, 보통 URL을 줍니다. 이 링크에는 시간 제한이 있을 수 있으므로 신속하게 다운로드하세요.
def save_image(job: dict, path: str) -> None:
url = job["output"]["image_url"]
for attempt in range(3):
try:
with requests.get(url, stream=True, timeout=60) as r:
r.raise_for_status()
with open(path, "wb") as f:
for chunk in r.iter_content(chunk_size=8192):
f.write(chunk)
return
except requests.RequestException:
if attempt == 2:
raise
time.sleep(2 ** attempt)
프로덕션에서 채택할 가치가 있는 방법:
- 스트리밍 다운로드. 생성된 이미지는 작지 않습니다; 이유 없이 전체를 메모리에 로드하는 것은 낭비입니다.
- 임시 경로에 쓰고 나서 이름을 바꾸세요. 쓰기 도중 충돌이 파이프라인이 유효한 이미지를 기대하는 위치에 잘린 파일을 남기면 안 됩니다.
- 생성이 아닌 다운로드를 재시도하세요. 불안정한 버킷 가져오기 재시도는 비용이 저렴하지만, 생성 한 번을 낭비하는 것은 그렇지 않습니다. 재시도 횟수를 제한하고 지수 백오프를 사용하세요.
- 작업 id를 파일과 함께 지속화하세요. 누군가 이미지가 어디서 왔는지 물을 때, 답은 로그를 뒤지는 것이 아니라 한 번의 쿼리여야 합니다.
객체 스토리지의 경우 open()을 SDK의 스트리밍 업로드로 교체하고 동일한 재시도 셸을 유지하세요.
오류, 재시도 및 비용 합리성 점검
가장 먼저 마주칠 실패 모드와 각각의 처리 방법:
- 401 / 인증 오류—키 누락, 오타, 또는 스크립트를 실행하는 셸에 내보내지 않음. 페이로드를 건드리기 전에 환경을 먼저 확인하세요.
- 4xx 검증 오류—보통 모델 id 오타,
prompt누락, 또는 잘못된 형식의 스타일 참조. 응답 본문을 그대로 기록하세요; 검증 메시지가 여기서 가장 빠른 해결 경로입니다. - 429 / 속도 제한—즉시 재시도하지 말고 지터 백오프를 사용하세요. 제출 함수 앞에 큐를 두는 것이 재시도 폭풍보다 낫습니다.
- 작업 타임아웃—폴링 데드라인이 발동했습니다. 재제출할지 의도적으로 결정하세요; 맹목적으로 재제출하면 성공률을 높이지 않고 지출을 두 배로 늘립니다.
- 일시적 네트워크 오류—상한이 있는 지수 백오프로 제출과 다운로드를 재시도하세요. 다운로드 실패는 자유롭게 재시도하고, 생성은 신중하게 재시도하세요.
비용 규율, 실용적 관점에서:
- 청구는 모델이 실제로 수행한 작업을 따르므로 실패한 작업과 포기된 배치는 숨은 비용입니다. 모든 제출과 그 프롬프트 해시 및 작업 id를 기록하여 나중에 사용량을 정산하세요.
- 가능한 가장 저렴한 프롬프트로 반복하세요. 소규모의 빠른 실행에서 문구와 스타일 참조를 조정한 후 대규모 배치에 투입하세요.
- 중복 제거. 동일한 프롬프트와 스타일 세트가 두 번 요청되면 자체 캐시에서 첫 번째 결과를 제공하세요.
- 워커 프로세스에 하드 동시성 상한을 추가하세요. 제한을 높이는 것이 예상치 못한 청구서를 설명하는 것보다 쉽습니다.
제출, 폴링, 저장을 세 개의 독립적이고 테스트 가능한 함수로 두면 이 엔드포인트는 어떤 파이프라인에도 깔끔하게 통합됩니다. 정확한 필드 이름, 상태, 현재 가격에 대해서는 통합 전에 hiapi의 recraft-v4-styles-pro/text-to-image 모델 페이지를 확인하세요.
관련 글
모든 아티클 보기 →-
튜토리얼
HiAPI API로 hailuo-2.3-fast/image-to-video 호출하는 방법: curl과 Python 실전
빠르고 저렴한 이미지-투-비디오 등급의 첫 실행 요청 — 모델 ID부터 MP4 다운로드까지
-
튜토리얼
HiAPI API로 hailuo-2.3/text-to-video를 호출하는 방법: curl, Python 및 실행 가능한 요청 예시
-
튜토리얼
HiAPI에서 Kandinsky 6.0 Pro 텍스트-투-비디오 사용하기: curl 및 Python 튜토리얼
요청 우선 실전 데모: 프롬프트에서 비디오 클립까지의 호출 구성, 요청 제출, 완료 상태 폴링 및 결과 다운로드