작성자 주: Nano Banana 2 API 응답에 포함된 thoughtSignature 필드의 본질을 깊이 파헤쳐 봅니다. 이는 이미지가 아니라 암호화된 사고 서명(Thinking Signature)입니다. Thinking 모드의 응답 구조와 올바른 처리 방법, 그리고 흔히 겪는 시행착오를 자세히 설명해 드립니다.
많은 개발자가 Nano Banana 2 API를 사용하여 이미지를 생성할 때, 응답 데이터에 이미지 데이터 외에도 thoughtSignature라는 필드가 포함된 것을 발견하곤 합니다. 이 필드 역시 긴 base64 인코딩 문자열로 되어 있어 마치 이미지 데이터처럼 보이죠. 디코딩을 시도해 봐도 이미지로 변환되지 않는데, 도대체 이것의 정체는 무엇일까요? 이번 글에서는 thoughtSignature의 본질과 이것이 왜 이미지가 아닌지, 그리고 다중 대화(멀티턴) 상황에서 어떻게 올바르게 처리해야 하는지 완벽하게 정리해 드립니다.
핵심 가치: 이 글을 읽고 나면 thoughtSignature의 기술적 원리를 이해하고, 이를 이미지로 착각하여 발생하는 오류를 방지하며, 다중 대화에서 올바르게 서명을 전달하는 방법을 마스터하게 될 것입니다.

Nano Banana 2 API thoughtSignature 핵심 요점
가장 많이 묻는 질문부터 바로 답변해 드릴게요. thoughtSignature는 이미지가 아니며, 이미지로 디코딩할 수도 없습니다. 이는 모델의 사고 과정을 담은 암호화된 서명입니다.
| 요점 | 설명 | 개발자 주의사항 |
|---|---|---|
| 본질 | 암호화 서명의 base64 인코딩 바이너리 데이터 | 디코딩, 수정, 위조 불가 |
| 내용 | 모델 추론 과정의 내부 상태 스냅샷 | 개발자에게는 완전히 불투명함 |
| 용도 | 다중 턴 대화에서 추론 연속성 유지 | 다음 요청 시 반드시 그대로 전달해야 함 |
| 형식 | base64 이미지처럼 보이지만 아님 | 매직 바이트가 없어 이미지 형식으로 인식 불가 |
| 강제성 | 도구 호출 시 반드시 전달해야 함 (누락 시 400 에러) | 텍스트 전용 시나리오에서는 생략 가능하나 품질 저하 발생 |
Nano Banana 2 API 응답에서 thoughtSignature 확인하기
Nano Banana 2를 호출하여 이미지를 생성할 때, API 응답의 parts 배열에는 여러 요소가 포함될 수 있습니다. 일반적인 응답 구조는 다음과 같습니다.
{
"candidates": [{
"content": {
"role": "model",
"parts": [
{
"text": "이미지를 생성하는 방법을 고민 중입니다...",
"thought": true
},
{
"text": "",
"thoughtSignature": "CpcHAdHtim9+q4rstcbvQC0ic4x1/vqQlCJ..."
},
{
"inlineData": {
"mime_type": "image/png",
"data": "iVBORw0KGgoAAAANSUhEUg..."
}
}
]
}
}]
}
여기에는 세 개의 part가 포함되어 있습니다.
- 사고 요약 (
thought: true): 모델 추론 과정의 텍스트 개요 - 사고 서명 (
thoughtSignature): 암호화된 추론 상태 스냅샷 - 이미지 데이터 (
inlineData): 실제 이미지 base64 데이터
핵심 문제는 2번과 3번 part 모두 base64 인코딩 데이터를 포함하고 있다는 점입니다. 코드에서 이를 제대로 구분하지 않으면 thoughtSignature를 이미지 데이터로 착각해 디코딩을 시도하게 되고, 결국 이미지 변환에 실패하게 됩니다.

Nano Banana 2 API thoughtSignature 기술 원리
thoughtSignature가 이미지가 아니라는 점을 이해했으니, 이제 이것이 정확히 무엇인지 살펴보겠습니다.
thoughtSignature의 본질
Google 공식 문서의 정의는 다음과 같습니다:
thoughtSignature(string, 선택 사항): "후속 요청에서 재사용할 수 있도록 하는 사고 과정의 불투명한 서명입니다. base64로 인코딩된 문자열입니다."
쉽게 풀어서 설명하자면, thoughtSignature는 모델 사고 과정의 '메모리 스냅샷'이며, 암호화된 서명을 거쳐 base64 인코딩 형태로 반환됩니다. 이 기능은 모델이 다중 턴 대화에서 이전의 추론 과정을 '기억'하여 사고의 일관성을 유지하도록 돕습니다.
주요 특징은 다음과 같습니다:
- 불투명함(Opaque): 개발자는 내용을 해석할 수 없으며, 내부 구조를 신경 쓸 필요도 없습니다.
- 암호학적 서명: Google 서버에서 서명하므로 위조가 불가능합니다. 무작위 base64 문자열을 전달하면 '유효하지 않은 서명' 오류가 발생합니다.
- 상태 유지(Stateful): 모델이 현재 답변을 생성할 때의 추론 체인과 중간 계산 결과를 포함합니다.
thoughtSignature와 thought의 차이점
이 두 필드는 자주 혼동되지만, 완전히 다른 개념입니다.
| 필드 | 타입 | 의미 | 가독성 | 용도 |
|---|---|---|---|---|
| thought | boolean | 현재 part가 사고 요약인지 표시 | 읽기 가능(텍스트) | 모델 추론 과정 표시 |
| thoughtSignature | string(base64) | 암호화된 추론 상태 스냅샷 | 읽기 불가능(암호문) | 다중 턴 대화 시 추론 상태 전달 |
thought는 사람이 읽기 위한 추론 요약이고, thoughtSignature는 모델이 '참조'하기 위한 추론 기억입니다.
Nano Banana 2 API에서 thoughtSignature가 필요한 이유
Nano Banana 2는 Gemini 3.1 시리즈에 속하며 Thinking(사고) 모드를 지원합니다. 모델은 이미지를 생성하기 전에 내부적으로 추론 과정을 거칩니다. 예를 들어 프롬프트 의도 분석, 구도 설계, 색상 구성 선택 등이 여기에 해당합니다.
이 추론 과정의 전체 상태가 압축 및 암호화되어 thoughtSignature가 됩니다. 다중 턴 대화에서 이미지 편집(예: "배경을 파란색으로 바꿔줘")을 수행할 때, 모델은 이전의 추론 상태를 복원해야만 수정 의도를 정확하게 이해할 수 있습니다.
thoughtSignature를 다시 전달하지 않으면 다음과 같은 문제가 발생합니다:
- 텍스트 전용 시나리오: 오류는 없지만, 추론 품질과 일관성이 저하됩니다.
- 도구 호출/함수 호출 시나리오: 즉시 HTTP 400 오류가 발생합니다.
- 이미지 편집 다중 턴 대화: 컨텍스트를 잃어버려 편집 결과가 부정확해질 수 있습니다.
🎯 개발 팁: 모든 다중 턴 대화 시나리오에서는
thoughtSignature를 온전히 보존하고 다시 전달해야 합니다.
APIYI(apiyi.com)를 통해 호출하면 플랫폼이 자동으로 서명 전달과 형식 호환성을 처리하므로, 개발자가 수동으로 관리할 필요가 없습니다.
Nano Banana 2 API thoughtSignature 올바른 처리 방법
간단한 예제: 응답을 올바르게 파싱하고 이미지와 서명 구분하기
다음 코드는 Nano Banana 2 응답에서 이미지를 올바르게 추출하고, 후속 작업을 위해 thoughtSignature를 저장하는 방법을 보여줍니다.
from google import genai
from google.genai import types
client = genai.Client(api_key="YOUR_API_KEY")
response = client.models.generate_content(
model="gemini-3.1-flash-image-preview",
contents=["벚꽃 나무 아래에 있는 하얀 고양이를 그려줘"],
config=types.GenerateContentConfig(
response_modalities=["TEXT", "IMAGE"],
image_config=types.ImageConfig(image_size="2K"),
thinking_config=types.ThinkingConfig(
include_thoughts=True
),
)
)
saved_signature = None
for part in response.parts:
if hasattr(part, 'thought') and part.thought:
print(f"사고 과정: {part.text[:100]}...")
elif hasattr(part, 'thought_signature') and part.thought_signature:
saved_signature = part.thought_signature # 저장, 디코딩하지 마세요!
print("thoughtSignature 저장 완료(이미지 아님)")
elif image := part.as_image():
image.save("cat_sakura.png", format="PNG")
print("이미지 저장 완료")
다중 턴 대화에서 thoughtSignature를 다시 전달하는 전체 코드 보기
from google import genai
from google.genai import types
client = genai.Client(api_key="YOUR_API_KEY")
# 1라운드: 이미지 생성
response1 = client.models.generate_content(
model="gemini-3.1-flash-image-preview",
contents=["벚꽃 나무 아래에 있는 하얀 고양이를 그려줘"],
config=types.GenerateContentConfig(
response_modalities=["TEXT", "IMAGE"],
image_config=types.ImageConfig(image_size="2K"),
thinking_config=types.ThinkingConfig(
include_thoughts=True
),
)
)
# 이미지와 서명 추출
image_data = None
thought_signature = None
model_parts = []
for part in response1.parts:
model_parts.append(part) # 전체 parts 보존
if hasattr(part, 'thought_signature') and part.thought_signature:
thought_signature = part.thought_signature
elif image := part.as_image():
image.save("round1.png", format="PNG")
# 2라운드: 이전 결과를 바탕으로 편집
# 핵심: 이전 라운드의 전체 parts(thoughtSignature 포함)를 이력으로 전달
history = [
{"role": "user", "parts": [{"text": "벚꽃 나무 아래에 있는 하얀 고양이를 그려줘"}]},
{"role": "model", "parts": model_parts}, # thoughtSignature 포함
]
response2 = client.models.generate_content(
model="gemini-3.1-flash-image-preview",
contents=history + [
{"role": "user", "parts": [{"text": "배경을 밤하늘로 바꾸고 달을 추가해줘"}]}
],
config=types.GenerateContentConfig(
response_modalities=["TEXT", "IMAGE"],
image_config=types.ImageConfig(image_size="2K"),
)
)
for part in response2.parts:
if image := part.as_image():
image.save("round2_edited.png", format="PNG")
print("편집된 이미지 저장 완료")
팁: APIYI(apiyi.com)를 통해 Nano Banana 2를 호출하면 OpenAI 호환 형식 인터페이스를 제공하여 thoughtSignature 전달을 자동으로 처리하므로, 다중 턴 대화의 서명 상태를 수동으로 관리할 필요가 없습니다.
Nano Banana 2 API thoughtSignature 관련 흔한 실수와 해결책
실수하기 쉬운 상황 요약
| 상황 | 문제 | 원인 | 해결책 |
|---|---|---|---|
| 서명을 이미지로 디코딩 | base64 디코딩 후 이미지가 아님 | thoughtSignature는 암호화된 데이터임 | inlineData 필드가 있는지 확인 후 디코딩 |
| 멀티턴 대화에서 서명 유실 | 후속 응답 품질 저하 또는 400 에러 | 서명을 다시 전달하지 않음 | 서명을 포함한 전체 parts를 저장하여 다음 턴에 전달 |
| 서명 위조 | "invalid signature" 에러 발생 | 서명에 암호화 검증이 포함됨 | API가 원본으로 반환한 값을 그대로 사용해야 함 |
| 필드명 불일치 | Python과 REST의 필드명이 다름 | REST는 camelCase, SDK는 snake_case 사용 | REST: thoughtSignature, Python: thought_signature |
| 스트리밍 응답 누락 | 서명 데이터가 누락됨 | 마지막 청크의 빈 text part에 서명이 있을 수 있음 | text가 비어있더라도 서명 필드를 반드시 확인 |
Nano Banana 2 API thoughtSignature 필드명 대조
호출 방식에 따라 필드명이 달라지는 점은 많은 개발자가 겪는 또 다른 함정입니다.
| 호출 방식 | 필드명 | 위치 |
|---|---|---|
| REST API (원본 JSON) | thoughtSignature |
parts[].thoughtSignature |
| Python SDK | thought_signature |
part.thought_signature |
| OpenAI 호환 형식 (중계) | thought_signature |
provider_specific_fields.thought_signature |
Nano Banana 2 API 비상 대책: 더미(dummy) 서명
기존 대화 기록을 마이그레이션하거나 유효한 thoughtSignature가 없는 경우, Google에서 제공하는 특수 우회 값을 사용할 수 있습니다.
# 유효한 서명이 없을 때 사용하는 임시 값
DUMMY_SIGNATURE = "context_engineering_is_the_way_to_go"
이 문자열을 thoughtSignature 값으로 전달하면 400 에러를 피할 수 있습니다. 다만, 이는 임시 방편일 뿐이며 모델의 추론 일관성에 영향을 줄 수 있습니다.
🎯 모범 사례: 첫 번째 호출부터 모든
thoughtSignature를 온전히 저장하여 올바른 대화 기록 체인을 구축하세요.
수동 관리가 복잡하게 느껴진다면, APIYI(apiyi.com)를 통해 OpenAI 호환 인터페이스를 사용하면 복잡도를 크게 낮출 수 있습니다.

자주 묻는 질문(FAQ)
Q1: thoughtSignature의 base64 데이터를 디코딩하면 무엇이 나오나요?
아무런 의미 있는 내용을 확인할 수 없습니다. 이는 암호화된 서명이 포함된 바이너리 데이터로, 설계상 내부를 들여다볼 수 없도록(opaque) 만들어졌습니다. base64로 디코딩하면 바이너리 바이트를 얻을 수는 있지만, 이는 이미지, 텍스트, JSON 등 알려진 어떤 파일 형식도 아닙니다. 유일한 올바른 처리 방법은 받은 그대로 저장하고, 그대로 다시 전달하는 것뿐입니다.
Q2: thoughtSignature를 다시 전달하지 않으면 어떻게 되나요?
두 가지 상황이 발생합니다. 1) 일반 텍스트 대화 시, 오류는 발생하지 않지만 모델 추론의 일관성이 떨어져 후속 답변의 품질이 기대에 미치지 못할 수 있습니다. 2) 도구 호출(function calling) 시, Gemini 3 시리즈 모델은 즉시 HTTP 400 오류를 반환합니다. Nano Banana 2의 이미지 편집 다중 대화에서 서명을 누락하면 모델이 컨텍스트를 제대로 복구하지 못해 편집 결과가 부정확해질 수 있습니다. APIYI(apiyi.com)를 통해 OpenAI 호환 인터페이스를 사용하면 플랫폼에서 자동으로 서명을 처리해주므로 이를 권장합니다.
Q3: 응답에서 이미지와 서명을 어떻게 구분하나요?
필드 타입을 확인하면 됩니다. inlineData(mime_type 및 data 포함)가 있는 part는 이미지 데이터이고, thoughtSignature / thought_signature 필드가 있는 part는 서명입니다. thought: true인 part는 사고 요약 텍스트입니다. 코드로 구현할 때는 inlineData가 존재하는지 먼저 확인한 후 다른 필드를 체크하는 것이 좋습니다.
Q4: 기존 대화 기록에 thoughtSignature가 없는데 어떻게 보완하나요?
Google은 "context_engineering_is_the_way_to_go"라는 특수한 더미 서명 값을 제공합니다. 이를 thoughtSignature의 임시 값으로 전달하여 400 오류를 방지할 수 있습니다. 다만, 이는 호환성을 위한 방편일 뿐 실제 추론 복구 기능은 없습니다. 장기적으로는 새로운 대화부터 모든 서명을 온전히 저장하는 것을 권장합니다.
요약
Nano Banana 2 API에서 thoughtSignature의 핵심 포인트는 다음과 같습니다:
- 이미지가 아님:
thoughtSignature는 암호화된 사고 과정 서명이며, base64 이미지 데이터가 아니므로 어떤 이미지 형식으로도 디코딩할 수 없습니다. - 반드시 그대로 전달: 다중 대화 시
thoughtSignature를 저장하고 그대로 다시 전달해야 합니다. 그렇지 않으면 도구 호출 시 400 오류가 발생하거나 텍스트 대화 품질이 저하됩니다. - 세 가지 part 구분:
inlineData가 있으면 이미지,thoughtSignature가 있으면 서명,thought: true이면 사고 요약입니다.
이 필드의 본질을 이해하면 Nano Banana 2 API 응답을 처리할 때 "서명을 이미지로 착각하여 디코딩하는" 실수를 피할 수 있습니다.
APIYI(apiyi.com)를 통해 Nano Banana 2의 다중 대화 이미지 편집 기능을 빠르게 테스트해 보세요. 플랫폼에서 자동으로 thoughtSignature 전달을 처리하며, 무료 크레딧과 통합 인터페이스를 제공합니다.
📚 참고 자료
-
Thought Signatures 공식 문서: Google의 thoughtSignature 메커니즘에 대한 전체 설명
- 링크:
ai.google.dev/gemini-api/docs/thought-signatures - 설명: 필드 정의, 전달 규칙 및 멀티턴 대화 예시 포함
- 링크:
-
Gemini Thinking 모드 문서: Thinking 기능 활성화 방법 및 구성 매개변수
- 링크:
ai.google.dev/gemini-api/docs/thinking - 설명: include_thoughts, thinking_level 등의 설정 방법 확인
- 링크:
-
Vertex AI 추론 API 참조: REST API 내 Part 객체의 전체 필드 정의
- 링크:
docs.cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference - 설명: thoughtSignature의 타입 정의 및 사용 제한 사항 포함
- 링크:
-
APIYI 문서 센터: OpenAI 호환 인터페이스를 통해 Nano Banana 2를 호출하는 간소화된 솔루션
- 링크:
docs.apiyi.com - 설명: thoughtSignature 전달을 자동으로 처리하여 개발 복잡도 감소
- 링크:
저자: APIYI 기술 팀
기술 교류: 댓글로 자유롭게 의견을 나눠주세요. 더 많은 자료는 APIYI 문서 센터(docs.apiyi.com)에서 확인하실 수 있습니다.
