튜토리얼
hiapi에서 Nano-Banana로 캐릭터 일관성 유지하기: 스토리보드와 이커머스에 바로 쓸 수 있는 워크플로
캐릭터 바이블(character bible) 기법은 같은 얼굴, 같은 의상, 같은 분위기를 전혀 다른 장면에서도 안정적으로 유지합니다——hiapi의 비동기 /v1/tasks 엔드포인트를 통해 Nano-Banana에서 엔드투엔드로 시연하며, 현재 예상 예산은 $0.41입니다.
요약
반복 등장하는 캐릭터를 생성해 본 적이 있다면——스토리보드 마스코트, 브랜드 앰버서더, 이커머스 피팅 모델——실패 패턴을 이미 잘 알 것입니다. 매 렌더링이 "대충 비슷해 보이는 사람"이고, 두 프레임을 나란히 놓는 순간 차이가 눈에 띄게 드러납니다. hiapi의 Nano-Banana 시리즈는 바로 이 문제를 위해 튜닝되었습니다. 이 글은 제가 실제로 사용하는 워크플로입니다:
- hiapi의 세 가지 Nano-Banana 모델 모두 캐릭터 일관성 태그를 갖고 있습니다:
nano-banana(고정 $0.05),nano-banana-2(1K / 2K / 4K 각각 $0.036 / $0.057 / $0.086), 그리고nano-banana-pro(1K와 2K는 $0.057, 4K는 $0.10). 세 가지 모두POST /v1/tasks뒤의 비동기 태스크입니다. - 핵심은 참조 이미지가 아니라 캐릭터 바이블입니다. 밀도 높고 반복 가능하며 결정적인 설명 문자열을 모든 장면별 프롬프트 앞에 접두사로 붙입니다. 이미지 투 이미지도, 파인튜닝도, LoRA도 필요 없습니다. 모델 업그레이드를 견디며 소스 컨트롤에서 버전 관리하기도 매우 쉽습니다.
- 이 글의 두 가지 데모는 모두 hiapi를 통해 실시간 렌더링됩니다: 같은 캐릭터("Mira")가 완전히 다른 조명과 장소에 등장하는 4컷 스토리보드 시퀀스, 그리고 같은 모델("Aria")이 한 번의 의상 교체를 수행하는 3컷 이커머스 시퀀스입니다.
- Nano-Banana 렌더링 7장의 총비용은 $0.35입니다. 품질을 나란히 비교하기 위해 Pro 등급의 Mira를 한 장 추가로 렌더링하는 비용은 $0.057입니다. 이 글의 총 예상 예산: $0.41.

"캐릭터 일관성"은 실제로 무엇을 뜻하는가
일관성은 단일 속성이 아니라, 여러 번의 렌더링에서 동시에 성립해야 같은 사람처럼 느껴지는 작은 속성들의 집합입니다:
- 얼굴 기하학. 눈 간격, 코 길이, 턱 너비, 볼의 부피감.
- 피부와 모발 표식. 피부톤, 주근깨나 점, 머리색과 머릿결.
- 의상과 액세서리. 그 특정 재킷, 그 특정 비니, 그 특정 공구 벨트.
- 분위기. 자세와 표정의 레퍼토리——이 캐릭터가 자신을 드러내는 방식.
프롬프트가 충분히 밀도 있을 때, hiapi의 Nano-Banana 모델은 1, 2, 3번을 잘 처리합니다. 4번은 저자——당신——의 몫입니다. 외형만이 아니라 자세와 표정 단서를 캐릭터 바이블에 담아야 합니다.
hiapi의 세 가지 Nano-Banana 모델
작성 시점의 실시간 /api/pricing 카탈로그에서 발췌:
| 모델 | 해상도 등급 | 가격(USD/장) | 선택 이유 |
|---|---|---|---|
nano-banana |
종횡비만, 해상도 파라미터 없음 | 고정 $0.05 | 빠른 반복. 캐릭터 초안을 잡는 모델. |
nano-banana-2 |
1K / 2K / 4K | $0.036 / $0.057 / $0.086 | 4K 출력, 작은 글자 렌더링 능력이 훨씬 뛰어남. 현재 정책에서 2K 등급이 1K보다 비쌈. |
nano-banana-pro |
1K / 2K / 4K | $0.057 / $0.057 / $0.10 | 더 선명한 디테일, 더 깊은 미세 특징, 급격한 장면 변화에서도 정체성 유지가 가장 견고함. |
세 가지 모두 input.prompt와 input.aspect_ratio를 받습니다. Pro와 -2 변형은 추가로 input.resolution(1K / 2K / 4K 중 하나)을 받습니다. 고정 가격 nano-banana는 resolution 필드를 400으로 거부합니다——등급형 모델을 선택했을 때만 설정하세요.
제 경험 규칙:
nano-banana-2의 1K 등급에서 바이블을 반복 개선——$0.036은 현재 세 가지 중 가장 저렴합니다.- 프로덕션 배치는
nano-banana-2의 1K 또는 2K 등급에서 렌더링. 2K 가격은 $0.057로 Pro와 같으므로, 어차피 2K가 필요하다면 Pro를 시도해 볼 가치가 있습니다. - 키 비주얼 샷——최종적으로 홈페이지, 미디어 키트, 인쇄판 룩북에 실리는 프레임——은
nano-banana-pro로.
캐릭터 바이블 기법
캐릭터 바이블은 해당 캐릭터의 모든 프롬프트 앞에 접두사로 붙이는 밀도 높은 문단입니다. 모델이 흔들릴 틈이 없을 만큼 구체적이어야 하지만, 장면을 펼칠 여지를 없앨 만큼 규정적이어서는 안 됩니다.
이 글의 스토리보드 캐릭터를 위해 제가 작성한 정확한 바이블입니다:
MIRA = (
"Mira, a 28-year-old field engineer of mixed Filipina–Polish "
"heritage, warm olive skin, narrow oval face, dark almond eyes "
"with light crow's-feet, thick straight black eyebrows, a small "
"mole on the right cheek, shoulder-length wavy black hair tied "
"loosely behind, rust-orange beanie with a small embroidered "
"antenna patch, dust-faded denim jacket over a graphite grey "
"t-shirt, dark cargo trousers, scuffed brown leather work boots, "
"a battered yellow toolbelt, friendly determined expression. "
"Cinematic photography, 35mm lens look, natural film grain, "
"neutral colour grade."
)
이 바이블에는 여섯 가지 의도적인 설계가 있습니다:
- 이름을 붙인다. "Mira"는 모델에게 안정적인 핸들을 제공합니다. 이름이 이미지에 나타나지 않더라도, 프롬프트에 이름이 있으면 정체성을 고정하는 것으로 보입니다.
- 혼혈 배경을 명시하고, 양쪽을 모두 지목한다. "여자"나 "아시아인"은 모호합니다. "필리핀–폴란드"는 모델을 구체적인 얼굴 융합으로 몰아갑니다.
- 눈, 눈썹, 머리, 피부를 각각 따로 묘사한다. "예쁘다"나 "자연스럽다"에 기대지 마세요. 기하학을 명확히 적으세요.
- 독특한 얼굴 표식 하나. 오른쪽 볼의 점. 가끔 움직이더라도, 이 표식이 모델을 특정 정체성 공간으로 밀어 넣습니다.
- 의상은 느슨한 묘사가 아니라 지목으로. "작은 자수 안테나 패치가 달린 녹슨 주황색 비니"는 반복 가능합니다. "모자"는 안 됩니다.
- 끝에 사진 스타일 도장 하나. "Cinematic photography, 35mm lens look, natural film grain, neutral colour grade." 이것이 원래 전혀 다른 장면들 사이의 조명 언어를 일관되게 유지합니다.
그러면 장면별 프롬프트는 단순히 바이블 + 구분자 + 짧은 장면 문단입니다. 저는 " | Scene: "를 구분자로 씁니다. 로그에서 읽기 명확하고, 모델은 뒷부분을 새 요청으로 취급합니다.
hiapi 비동기 태스크 엔드포인트 호출
hiapi의 모든 이미지 모델은 동일한 비동기 패턴을 따릅니다: POST /v1/tasks로 생성, GET /v1/tasks/{taskId}로 폴링, 성공 시 data.output[0].url에서 렌더링 이미지를 읽습니다. 출력 URL은 짧게 유효하므로(expireAt 포함) 바이트를 즉시 스토리지로 다운로드하세요.
import os, json, subprocess, time
API = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_TOKEN"]
def submit(model: str, prompt: str, aspect_ratio: str,
resolution: str | None = None) -> str:
payload = {
"model": model,
"input": {"prompt": prompt, "aspect_ratio": aspect_ratio},
}
# Only nano-banana-pro and nano-banana-2 accept `resolution`.
# The flat-priced nano-banana returns 400 on the extra field.
if resolution and model in ("nano-banana-pro", "nano-banana-2"):
payload["input"]["resolution"] = resolution
r = subprocess.run(
["curl", "-s", "-X", "POST", API,
"-H", f"Authorization: Bearer {TOKEN}",
"-H", "Content-Type: application/json",
"-d", json.dumps(payload)],
capture_output=True, text=True, timeout=70,
)
data = json.loads(r.stdout)
return data["data"]["taskId"]
def wait(task_id: str, timeout_s: int = 600) -> str:
deadline = time.time() + timeout_s
while time.time() < deadline:
r = subprocess.run(
["curl", "-s", f"{API}/{task_id}",
"-H", f"Authorization: Bearer {TOKEN}"],
capture_output=True, text=True, timeout=40,
)
task = json.loads(r.stdout)["data"]
if task["status"] == "success":
return task["output"][0]["url"]
if task["status"] == "fail":
raise RuntimeError(task["error"])
time.sleep(6)
raise RuntimeError(f"timeout: {task_id}")
def render(model, scene, ratio, bible, resolution=None):
prompt = f"{bible} | Scene: {scene}"
return wait(submit(model, prompt, ratio, resolution))
Nano-Banana의 경우 6초 폴링 간격이 적절한 기본값입니다——상태가 좋은 날에는 단일 이미지가 약 10–60초 안에 도착합니다. 더 촘촘한 폴링은 왕복만 낭비합니다.
데모 A —— 같은 캐릭터의 4컷 스토리보드
스토리보드의 핵심은 이것입니다: 이야기는 패널 사이에서 변하는 것이고 주인공은 상수입니다. 저는 완전히 동일한 Mira 바이블로 캐릭터 시트 한 장과 장면 샷 두 장을 생성하겠습니다.
1단계 —— 바이블 시각화
바이블을 저장소에 커밋하기 전에, 그것으로 캐릭터 시트를 렌더링하세요. 바이블이 충분히 고정력이 있는지 판단하는 가장 저렴한 방법입니다.
sheet = render(
"nano-banana", aspect_ratio="3:2", bible=MIRA, scene=(
"a character model sheet on a clean white studio background, "
"three views of Mira side by side — three-quarter view facing "
"left, full profile facing right, three-quarter back view — "
"same outfit, same hairstyle, same toolbelt, even neutral "
"studio lighting, no shadows, no text labels."
),
)

여기서 주목할 만한 일이 일어났습니다: 바이블에 "Cinematic photography, 35mm lens look"이 명시되어 있는데도 모델은 3D 카툰 시트를 만들어냈습니다. "model sheet"나 "character sheet"를 요청할 때 가장 흔한 실패 모드입니다——이 토큰들이 미학을 훈련 데이터셋의 애니메이션 업계 참고 자료 쪽으로 끌어당깁니다. 두 가지 대처 방식이 있습니다:
- 받아들인다. 시트는 바이블의 참고 문서이지 출시 결과물의 일부가 아닙니다. 의상, 액세서리, 대략적 비율이 보이는 것으로, 실제로 필요한 전부입니다.
- 장면 조각에
"shot on Kodak Portra 400, full-frame DSLR, no illustration, no toon, no 3D render"를 넣어 밀어붙인다——보통 포토리얼리즘으로 끌어오기에 충분합니다.
저는 여기서 1번 방식을 택했는데, 다음 두 장면 샷이 프로덕션 프레임이기 때문입니다.
2단계 —— 같은 Mira를 완전히 다른 두 환경에 배치
workshop = render("nano-banana", "3:2", MIRA, scene=(
"Mira in a cluttered repair workshop, leaning over a wooden "
"workbench under a single warm hanging bulb, reading a circuit "
"schematic on tablet, soldering iron beside her, walls lined "
"with scavenged parts, late evening, focused expression."
))
rooftop = render("nano-banana", "3:2", MIRA, scene=(
"Mira on a city rooftop in cold overcast morning light, kneeling "
"to bolt a small antenna mast to a ledge, wind moving her hair, "
"distant grey buildings, breath barely visible, concentrated "
"working expression."
))


두 장면은 환경적으로 공통점이 전혀 없습니다——좁은 실내 공간의 따뜻한 텅스텐 조명 대 넓은 옥상의 차가운 일광. 하지만 안테나 패치가 달린 녹슨 비니는 같고, 데님 재킷은 같고, 공구 벨트는 같으며, 얼굴은 두 이미지 모두에서 같은 젊은 여성으로 읽힙니다. 이것이 바이블이 작동하는 모습입니다.
장면 사이에 무엇이 변했는가 (그리고 변하지 않은 것)
| 속성 | 작업장 | 옥상 |
|---|---|---|
| 광온 | 따뜻한 텅스텐 | 차가운 흐림 |
| 자세 | 앉아서 몸을 숙임 | 무릎 꿇음 |
| 배경 | 어수선한 실내 | 탁 트인 도시 옥상 |
| 하루 중 시간 | 늦은 밤 | 이른 아침 |
| 비니 | ✅ 같은 녹슨 주황색 + 패치 | ✅ 동일 |
| 데님 재킷 | ✅ 같은 워시 | ✅ 동일 |
| 공구 벨트 | ✅ 같은 노란색 가죽 | ✅ 동일 |
| 얼굴 기하학 | ✅ 동일 | ✅ 동일 |
| 점 | 오른쪽 볼에 위치 | 존재(약간 흐림) |
마지막 줄이 가장 중요합니다. 완전히 다른 두 조명 상황에서 그 작은 점이 오른쪽 볼에 남아 있습니다. 이것이 바로 원하는 신호입니다.
데모 B —— 같은 모델의 3컷 이커머스 시퀀스
이커머스는 이 글의 두 데모 중 더 어려운 쪽입니다. 모델은 여러 각도와 의상 교체 사이에서 문자 그대로 완전히 동일하게 보여야 합니다. 브랜드 고객이 제품 상세 페이지에서 이 사진들을 머릿속으로 A/B 하기 때문입니다. 아주 작은 흔들림도 환상을 깨뜨립니다.
다음은 Aria의 바이블입니다:
ARIA = (
"Aria, a 26-year-old fashion catalogue model of Korean descent, "
"soft warm undertone skin, oval face with slightly defined "
"cheekbones, thin straight black eyebrows, dark brown almond "
"eyes, small natural lips with a faint warm pink, a single "
"beauty mark just below the left eye, centre-parted glossy "
"black hair falling straight to mid-back, ears pierced with a "
"single small gold stud each side, no other jewellery, calm "
"neutral expression, even soft studio lighting from front-left, "
"clean light grey seamless paper backdrop, full-body framing, "
"50mm portrait lens look, neutral colour balance, slight matte "
"film finish."
)
이 바이블은 Mira 바이블이 하지 않은 세 가지를 합니다:
- 조명과 배경을 고정합니다. 카탈로그 모델은 깔끔한 회색 배경과 평평한 좌전방 스튜디오 조명에 살아야 합니다. 둘 다 바이블에 적으면 매 렌더링이 여기서 시작합니다.
- 구도를 지정합니다. "Full-body framing, 50mm portrait lens look"은 세 이미지 모두에서 일관되게 재현됩니다.
- 여백을 못 박습니다. "No other jewellery"는 Nano-Banana가 렌더링 절반에서 체인이나 시계를 즉흥적으로 추가하는 것을 막는 작은 문구입니다.
1단계 —— 정면 메인 이미지
frontal = render("nano-banana", "3:4", ARIA, scene=(
"full-body straight-on frontal e-commerce shot, Aria standing "
"relaxed with arms at sides, wearing a structured rust-olive "
"wool blazer (single-breasted, two buttons, notch lapel, no "
"pattern) over a plain ivory crew-neck t-shirt and straight-leg "
"dark indigo denim jeans, simple white leather sneakers, clean "
"look-book composition."
))

재킷 렌더링에 대한 솔직한 설명 하나: 프롬프트는 녹슨 올리브색을 요구했지만 Nano-Banana는 따뜻한 담배 갈색으로 해석했습니다. Pantone 스타일의 특정 색상명("rust-olive", "burnt sienna", "ultramarine")은 생성에서 안정적으로 재현되지 않습니다. 브랜드 정확한 색상이 필요하다면 기본 이미지를 렌더링한 뒤 색상 전문화 모델에서 이미지 투 이미지를 한 번 실행하거나, 메인 이미지 순간에만 nano-banana-pro로 색상이 정확한 샘플 이미지를 한 장 구매하고 가격을 받아들이세요.
2단계 —— 같은 의상의 4분의 3 각도
side = render("nano-banana", "3:4", ARIA, scene=(
"full-body three-quarter angle from her right, Aria standing "
"relaxed, wearing the same structured rust-olive wool blazer "
"(single-breasted, two buttons, notch lapel, no pattern) over "
"a plain ivory crew-neck t-shirt and straight-leg dark indigo "
"denim jeans, simple white leather sneakers, hands by her "
"sides, look-book lighting."
))

이 부분이 캐릭터 일관성 데모에서 항상 무너지는 지점입니다: 같은 사람, 회전. 얼굴이 일관되어야 하고, 헤어스타일이 일관되어야 하며, 의상이 그녀 몸에 걸리는 방식도 일관되어야 합니다. 나란히 보면 두 사진은 같은 촬영처럼 읽힙니다——같은 모델, 같은 콜시트, 같은 메이크업 의자. 이것이 필요한 결과입니다.
3단계 —— 같은 모델, 완전히 다른 의상
swap = render("nano-banana", "3:4", ARIA, scene=(
"full-body straight-on frontal e-commerce shot, Aria standing "
"relaxed with arms at sides, now wearing an oversized "
"camel-coloured double-breasted wool overcoat (mid-thigh length, "
"wide lapels, large mother-of-pearl buttons) over a black "
"turtleneck and straight-leg charcoal trousers, black ankle "
"boots, look-book lighting."
))

이것이 Nano-Banana에 캐릭터 일관성 태그를 안겨준 데모입니다. 같은 얼굴, 왼쪽 눈 아래 같은 점, 같은 머리 길이와 가르마, 같은 금색 귀걸이, 같은 자세 어휘——의상과 실루엣만 바뀝니다. 가상 피팅 플로우, 자동 룩북 생성기, 대량 생산 PDP 촬영을 구축하고 있다면, 바로 이 변환을 수천 번 실행하게 될 것입니다.
언제 Nano-Banana-Pro를 써야 하는가
비용과 품질의 트레이드오프를 확인하기 위해, nano-banana-pro의 1K 등급에서 Mira를 한 장 추가로 렌더링했습니다. 현재 추정: $0.057:

같은 Mira 바이블. 같은 " | Scene: " 구분자. 모델 이름만 바꿨습니다. 이미지당 $0.007을 더 지불하면(Pro의 $0.057 대 고정 Nano-Banana의 $0.05) 실제로 얻는 것은:
- 더 선명한 미세 디테일——한 올의 머리카락, 데님 직조, 비니의 자수 패치.
- 덜 눈에 띄는 정체성 표식을 더 잘 유지——눈 모양과 눈썹 기울기가 Mira 시리즈의 나머지와 더 비슷하게 읽힙니다.
- 더 나은 작은 글자 렌더링. 장면에 간판, 라벨, 로고가 썸네일 크기에서 읽혀야 한다면 Pro가 원하는 것입니다.
고사용량 장면(예: 매일 수백 프레임의 스토리보드나 절차적 카탈로그 생성)에는 nano-banana-2의 1K 등급 $0.036이 적절한 기본값입니다. Pro는 1K와 2K 모두 $0.057로 nano-banana-2의 2K와 같으므로, 2K나 메인 이미지 프레임이 필요한 곳——커버 이미지, 룩북 메인 이미지, 마케팅 원페이지——에 사용하세요.
이 글의 현재 예상 예산
| 렌더링 | 모델 | 등급 | 현재 추정 |
|---|---|---|---|
| 커버(Mira 태양광 발전소) | Nano-Banana | 16:9 고정 | $0.05 |
| 캐릭터 시트 | Nano-Banana | 3:2 고정 | $0.05 |
| 스토리보드 1 —— 작업장 | Nano-Banana | 3:2 고정 | $0.05 |
| 스토리보드 2 —— 옥상 | Nano-Banana | 3:2 고정 | $0.05 |
| 이커머스 —— 정면 | Nano-Banana | 3:4 고정 | $0.05 |
| 이커머스 —— 측면 | Nano-Banana | 3:4 고정 | $0.05 |
| 이커머스 —— 의상 교체 | Nano-Banana | 3:4 고정 | $0.05 |
| Pro 비교 이미지 | Nano-Banana-Pro | 3:2, 1K | $0.057 |
| 총계 | $0.41 |
이미지 여덟 장, Bearer 토큰 하나, HTTP 엔드포인트 하나, SDK 조립 불필요, 업스트림 계정 관리 불필요——이것이 hiapi의 용도입니다.
제가 계속 되돌아오는 실용 규칙
- 바이블은 한 번만 작성하고, 소스 컨트롤에, 상수 모듈에 둔다. 다른 설정 문자열처럼 대하세요. 버전 관리하세요.
- 바이블마다 이름 하나. "Mira", "Aria". 모델이 이름을 표시하지 않더라도, 프롬프트에 있으면 안정적인 핸들입니다.
- 정체성 표식 세 개를 골라 강하게 의존한다. Mira는 안테나 패치가 달린 비니, 노란색 공구 벨트, 그 점입니다. Aria는 점, 중분할 머리, 금색 귀걸이입니다. 이 셋이 한 번의 렌더링에서 살아남으면 캐릭터도 살아남습니다.
- Pantone 스타일 색상명을 신뢰하지 않는다. "Rust-olive"는 담배 갈색으로 흔들렸습니다. 색상이 중요하면 먼저 렌더링 후 다운스트림 보정하거나, Pro를 쓰고 의도적으로 브랜드 샘플 이미지를 촬영하세요.
- 사진 스타일 도장을 바이블의 끝에 둔다. "Cinematic 35mm"나 "50mm portrait lens, slight matte film finish"——맨 끝에 두면 긴 프롬프트 잘림에서 살아남습니다.
- 캐릭터 시트를 먼저 렌더링하고, 카툰으로 흔들릴 것을 예상한다. 정상입니다. 시트는 당신을 위한 것이지 출시용이 아닙니다. 프로덕션 샷은 같은 바이블에 장면 내 프롬프트 조각을 더해 포토리얼리즘을 유지하세요.
- 초안과 양산에는
nano-banana-2의 1K($0.036), 메인 이미지 샷과 2K가 필요한 모든 것에는nano-banana-pro(1K 또는 2K 모두 $0.057). 클라이언트에 작은 스케줄러를 만들어quality파라미터로 모델을 선택하고 올바른 해상도를 전달하세요. - 고정 가격
nano-banana는resolution을 거부한다. 클라이언트에서 모델명으로 해당 필드를 게이트하세요. 피와 눈물로 배운 400입니다.
이것이 워크플로입니다. 바이블 하나를 가져와, 정체성 표식 세 개를 고르고, 장면 조각을 만들고, POST /v1/tasks로 트리거하면, 같은 사람이 매 렌더링의 반대편에서 걸어 나옵니다.
텍스트 바이블보다 참조 이미지 경로를 선호하나요? Ideogram 3.0 Character는 대신 업로드한 참조 이미지에서 캐릭터를 고정하며, 프롬프트 가이드는 마스코트, 동화책 페이지, 마스크 편집에서 같은 기법을 보여줍니다.
관련 글
모든 아티클 보기 →-
튜토리얼
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 튜토리얼
요청 우선 실전 데모: 프롬프트에서 비디오 클립까지의 호출 구성, 요청 제출, 완료 상태 폴링 및 결과 다운로드