AI 활용

Gemini API 응답이 비는 원인. gemini-2.5-flash는 thinkingBudget=0과 5건 분할로 해결

Gemini API 응답이 비는 원인. gemini-2.5-flash는 thinkingBudget=0과 5건 분할로 해결

안녕하세요, まさきん입니다.

Gemini API에 기사 10건을 한꺼번에 던졌더니 본문이 빈 채로 돌아왔습니다. 원인과 고치는 방법이 공식 문서로 설명되는 내용이었기에 메모로 남겨 둡니다.

※ 글 공개 시점의 정보입니다. 최신 조건은 공식 사이트에서 확인해 주세요.

POINT
  • Gemini API의 응답이 비어 있을 때는 먼저 finishReason과 usageMetadata를 본다
  • 공식 문서에 따르면 출력 토큰 상한(maxOutputTokens)은 사고 토큰을 포함한 합계에 적용된다
  • gemini-2.5-flash는 thinkingBudget을 0으로 하면 사고를 끌 수 있다(범위는 0~24576)
  • 저는 thinkingBudget=0으로 하고, 10건 일괄을 5건씩 나누었더니 통과했다
  • 본문에 없는 마감일이 만들어지는 경우가 있어서, 날짜는 후처리로 본문과 대조하고 있다

무엇을 만들고 있었나

어느 회원 전용 사이트의 새 글을 매일 가져오는 구조를 만들었습니다. 글마다 “혜택 정보인지 아닌지”의 판정과 요약을 Gemini에 맡기고 있습니다.

알림은 가족 채팅방으로 보내는 형태입니다. 전부 흘려보내면 아무도 읽지 않게 되므로, 혜택 정보로 판정된 것만으로 좁혔습니다.

모델은 gemini-2.5-flash입니다. 요약과 분류라는 정형 처리이니 빠르고 저렴한 모델이 맞겠다고 생각했습니다.

10건을 한꺼번에 던졌더니 본문이 비어 있었다

처음에는 새 글 10건을 한 번의 요청으로 묶었습니다. 호출 횟수를 줄이고 싶었기 때문입니다.

그런데 돌아온 응답의 본문이 비어 있었습니다. 오류로 멈춘 것은 아닙니다. 응답은 돌아오는데 내용이 없는 상태입니다.

오류라면 예외로 알아챌 수 있습니다. 빈 응답은 조용히 통과해 버리기 때문에 조금 까다로울 수 있습니다. 정형 처리에 넣을 때는 여기가 첫 번째 함정이라고 생각합니다.

원인은 사고에도 출력 한도를 쓴다는 것

공식 문서에서는 Gemini 3 계열과 2.5 계열이 “사고 과정”을 사용하는 모델이라고 설명합니다. 응답하기 전에 모델이 내부에서 추론을 하는 구조입니다.

이 사고는 기본값으로 켜져 있습니다. 공식 표현으로는 “동적 사고”이며, 요청의 복잡도에 맞춰 양이 자동으로 바뀝니다.

핵심은 이 사고에도 토큰이 쓰인다는 점입니다. 공식 문서에는 max_output_tokens가 사고 토큰을 포함한 상한이라고 적혀 있습니다.

사고 도중에 상한에 닿으면 finish_reason은 MAX_TOKENS가 됩니다. 그리고 출력은 도중에 끊기거나 빈 채로 돌아온다고 합니다. 10건분의 판정을 한 번에 생각하게 하면 사고와 출력의 합계가 부풀기 쉬운 것 같습니다.

주의

공식 문서에는 과금에 관한 주의도 적혀 있습니다. 상한에 도달해 출력이 비어 있어도, 생성된 사고 토큰은 과금 대상입니다. 빈 채로 돌아오는 상태는 결과도 없는데 비용만 나가는 꼴이 될 수 있습니다.

빈 응답이 돌아올 때의 원인 구분표

빈 응답에는 몇 가지 종류가 있습니다. API 레퍼런스에 있는 항목을 바탕으로 어디를 봐야 하는지 정리했습니다.

증상응답에서 볼 곳생각할 수 있는 상황대처 방향
본문이 비었거나 도중에 끊김finishReason이 MAX_TOKENS지정한 최대 토큰 수에 도달사고를 줄인다, 1회 건수를 줄인다, 상한을 다시 본다
본문이 비었고 사고가 많음usageMetadata.thoughtsTokenCount가 큼사고가 출력 한도를 쓰고 있음thinkingBudget을 낮춘다(2.5 계열)
본문이 비었는데 이유가 다름finishReason이 SAFETY 등안전성 등의 이유로 중단입력 내용과 프롬프트를 다시 본다
JSON은 돌아오지만 내용이 이상함finishReason은 STOP형식은 맞지만 값이 틀림앱 쪽에서 값을 검증한다

finishReason의 STOP은 자연스러운 종료 지점에서 멈췄다는 뜻입니다. MAX_TOKENS는 요청에서 지정한 최대 토큰 수에 도달했다는 뜻으로 정의되어 있습니다.

그러니 비어 있을 때 가장 먼저 볼 것은 finishReason이라고 생각합니다. STOP 이외의 값이 들어 있으면 본문은 쓰지 않는다는 전제로 해 두면 안전할 수 있습니다.

usageMetadata 읽는 법

응답에는 usageMetadata가 붙어 옵니다. API 레퍼런스에서는 다음과 같이 설명합니다.

항목의미
promptTokenCount프롬프트(입력)의 토큰 수
candidatesTokenCount생성된 응답 후보의 토큰 수 합계
thoughtsTokenCount사고 모델의 사고에 쓰인 토큰 수
totalTokenCount프롬프트+사고+응답 후보의 합계

합계가 “프롬프트+사고+응답”으로 정의되어 있다는 점이 알기 쉽습니다. 사고와 응답은 별개의 항목으로 집계됩니다.

사고 숫자가 크고 응답 숫자가 작다면 사고에 한도를 쓰고 있을 가능성이 있습니다. 이 두 가지를 로그에 남겨 두면 나중에 원인을 추적하기 쉽다고 생각합니다.

thinkingBudget 지정 방법

2.5 계열에서는 thinkingBudget이라는 파라미터로 사고의 양을 지정합니다. 공식 문서에서는 사고에 쓸 토큰 수의 기준을 모델에 알려 주는 것이라고 설명합니다.

0으로 하면 사고를 끌 수 있습니다. -1로 하면 동적 사고가 됩니다. Python SDK에서는 공식 예시를 따르면 이렇게 씁니다.

from google import genai
from google.genai import types

client = genai.Client()
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=prompt,
    config=types.GenerateContentConfig(
        thinking_config=types.ThinkingConfig(thinking_budget=0)
    ),
)

REST로 호출할 때는 generationConfig 안에 thinkingConfig를 둡니다. 그 안에서 thinkingBudget을 숫자로 넘기는 형태입니다.

다만 공식 문서에는 주의 사항도 있습니다. 프롬프트에 따라서는 모델이 예산을 넘거나 밑도는 경우가 있다고 합니다. 엄밀한 상한이라기보다 기준으로 다루는 편이 좋아 보입니다.

모델별 thinkingBudget 범위

범위와 기본값은 모델마다 다릅니다. 공식 문서의 표를 2.5 계열의 주요 모델로 좁혀서 옮겼습니다.

모델지정하지 않았을 때지정 가능한 범위사고 끄기동적 사고
2.5 Pro동적 사고128~32768불가-1(기본값)
2.5 Flash동적 사고0~245760을 지정-1(기본값)
2.5 Flash Lite사고하지 않음512~245760을 지정-1

2.5 Pro는 사고를 끌 수 없다는 점이 중요한 차이라고 생각합니다. “Flash에서 0으로 해 둔 설정”을 그대로 Pro로 가져가면 전제가 무너질 수 있습니다.

2.5 Flash Lite는 아무것도 지정하지 않으면 사고하지 않는 모델입니다. 요약이나 분류만 한다면 이쪽을 고르는 방법도 있다고 생각합니다.

Gemini 3 계열은 thinkingLevel로 지정한다

글 공개 시점의 공식 문서에서는 Gemini 3 계열 이후의 지정 방법이 바뀌어 있습니다. 권장되는 것은 thinkingLevel입니다. minimal, low, medium, high 같은 단계로 지정하는 형태입니다.

2.5 계열은 반대로 thinkingLevel을 지원하지 않습니다. 공식 문서에는 2.5 계열에서는 thinkingBudget을 쓰라고 적혀 있습니다.

Gemini 3 계열의 주의점도 실려 있었습니다. Gemini 3.1 Pro는 사고를 끌 수 없습니다. Gemini 3의 Flash와 Flash-Lite도 완전한 사고 끄기는 지원하지 않는다고 합니다. minimal 역시 “사고 끄기를 보장하는 것은 아니다”라는 설명입니다.

즉 모델을 새로 바꾸면 “0으로 해서 끈다”는 방법은 쓸 수 없게 될 가능성이 있습니다. 갈아탈 때는 설정을 다시 써야 한다고 생각해 두는 편이 좋아 보입니다.

2.5 계열을 쓸 수 있는지 먼저 확인한다

공식 모델 목록에는 2.5 계열에 관한 주석이 있습니다. 과거에 실제로 사용한 적이 있는 사용자로 이용을 한정하고 있다는 내용입니다.

지원 중단은 아니며 당분간 API로 계속 제공한다고도 적혀 있습니다. 다만 새 프로젝트에서는 최신 모델을 쓰도록 안내하고 있었습니다.

제 구조는 gemini-2.5-flash로 돌아가고 있습니다. 이제 새로 만드는 분은 먼저 자신의 프로젝트에서 쓸 수 있는 모델을 확인하는 것이 우선일 수 있습니다.

가입하지 않아도 100포인트를 받는 요금 시뮬레이션 AI로 매일의 정보 수집을 가볍게 했다면, 매달 휴대폰 요금도 라쿠텐 모바일에서 점검해 보기

누르면 라쿠텐 로그인 페이지가 열립니다. 로그인하면 캠페인 내용이 표시됩니다.

사고 토큰의 과금

요금 페이지에는 출력 요금이 “사고 토큰 포함”이라고 명시되어 있습니다. gemini-2.5-flash 칸도 같은 표기였습니다.

사고 가이드에도 같은 취지의 설명이 있습니다. 사고가 켜져 있을 때 응답 요금은 출력 토큰과 사고 토큰의 합계가 된다는 것입니다.

사고의 요약만 받도록 설정해도, 과금은 원래의 사고 토큰 전체가 대상이라고 합니다. 눈에 보이는 양보다 많이 집계될 수 있다고 이해하면 될 것 같습니다.

요약이나 분류 같은 정형 처리는 매일 반복해서 돌아갑니다. 1회분은 작아도 사고 몫이 쌓이는 구조는 알아 두어서 손해 볼 것이 없다고 생각합니다.

구조화 출력(JSON) 지정 방법

판정과 요약을 프로그램으로 받는다면 JSON으로 돌려받는 것이 다루기 쉽습니다. Gemini API에는 이를 위한 구조화 출력 기능이 있습니다.

API 레퍼런스에서는 generationConfig에 두 항목을 두는 형태입니다. responseMimeType에 application/json을 지정합니다. 아울러 responseJsonSchema에 스키마를 넘깁니다.

"generationConfig": {
  "responseMimeType": "application/json",
  "responseJsonSchema": {
    "type": "object",
    "properties": {
      "is_deal": {"type": "boolean"},
      "summary": {"type": "string"},
      "deadline": {"type": "string"}
    }
  }
}

항목 이름은 설명용으로 제가 넣은 예시입니다. 레퍼런스에는 스키마를 넘길 때 responseMimeType이 필수라고 적혀 있습니다.

참고로 SDK 가이드에는 쓰는 법이 조금 다른 예시도 실려 있었습니다. 사용 중인 SDK 버전에 맞춰 공식 예시를 다시 확인하는 것이 좋다고 생각합니다.

공식 베스트 프랙티스에는 중요한 한 문장이 있습니다. 구조화 출력은 구문상 올바른 JSON을 보장하지만, 값이 의미상 올바르다는 것은 보장하지 않습니다. 사용하기 전에 앱 쪽에서 검증하라고 적혀 있습니다.

5건씩 나눠서 통과시켰다

제가 실제로 한 대처는 두 가지입니다. thinkingBudget을 0으로 했습니다. 그리고 10건 일괄을 5건씩으로 나누었습니다.

이 두 가지를 넣었더니 본문이 돌아오게 되었습니다. 둘 중 하나만으로 충분했는지는 따로 확인하지 않았습니다.

비교 항목10건 일괄5건씩 분할
호출 횟수적다늘어난다
1회 출력 길이길어진다짧아진다
상한에 닿을 우려커지기 쉽다작아지기 쉽다
실패했을 때의 영향전체를 다시 실행그 묶음만 다시 실행
기사끼리 뒤섞임일어날 수 있다줄이기 쉽다

일괄 쪽이 효율은 좋아 보입니다. 다만 실패하면 전체를 다시 해야 하더라고요. 나눠 두면 실패 범위가 묶음 안에서 끝납니다.

몇 건씩이 최적인지는 기사 길이나 출력 형태에 따라 달라진다고 생각합니다. 5건이라는 숫자는 제 용도에서 마침 통과한 숫자입니다.

본문에 없는 마감일이 만들어지는 경우가 있다

또 하나 곤란했던 것이 마감일입니다. Gemini가 본문에 적혀 있지 않은 마감일을 만들어 내는 일이 있었습니다.

혜택 정보 알림에서 마감이 틀리면 곤란합니다. 너무 이르면 기회를 놓치고, 너무 늦으면 기한이 지난 것을 알아채지 못합니다.

이것은 구조화 출력의 주의 사항과 이어지는 이야기라고 생각합니다. JSON의 형태가 맞아도 값이 맞다는 보장은 없습니다. 스키마에 “마감” 칸이 있으면 채우려는 힘이 작용하는 것일지도 모릅니다.

날짜 문자열이 본문에 없는 마감은 버린다

대책으로 후처리를 넣었습니다. 생각은 단순합니다.

  1. Gemini가 마감일을 JSON 항목으로 돌려주게 한다
  2. 그 날짜에 해당하는 문자열이 원래 기사 본문에 있는지 확인한다
  3. 본문에서 찾지 못하면 마감 항목을 버린다
  4. 마감 없는 혜택 정보로 알린다

모델에 “만들지 말아 줘”라고 부탁하는 것만으로는 확실하지 않다고 느꼈습니다. 그래서 프로그램 쪽에서 본문과 맞춰 보는 형태로 했습니다.

이 방법에는 약점도 있습니다. 본문의 표기와 모델이 돌려주는 표기가 다르면 올바른 마감까지 버리게 됩니다. “틀린 마감을 내보내는 것보다 마감 없음이 낫다”고 선을 그은 설계입니다.

정형 처리에 넣을 때의 요령

이번 일로 정형 처리에 생성형 AI를 넣을 때의 관점이 조금 정리되었습니다.

CHECK
  • 빈 응답을 오류로 취급한다(본문 길이와 finishReason을 본다)
  • usageMetadata를 로그에 남겨 사고와 출력의 내역을 추적할 수 있게 한다
  • 요약이나 분류 같은 작업에서는 사고를 줄이는 설정을 먼저 검토한다
  • 한 번에 너무 많이 넣지 말고, 실패해도 묶음만 다시 실행할 수 있는 크기로 한다
  • 모델이 돌려준 값은 원래 본문과 대조한 뒤에 쓴다

공식 베스트 프랙티스에도 비슷한 예가 있습니다. 사실 추출이나 분류 같은 단순한 작업은 사고를 최소한이나 낮게 한다는 것입니다. 어려운 추론이 필요 없는 작업에 깊은 사고는 필요하지 않을지도 모릅니다.

업무에서도 숫자는 출처와 맞춰 본 뒤에 씁니다. AI의 출력도 똑같이 다루는 것이 가장 마음 편한 방식이라고 생각합니다.

매일 아침의 정보를 AI에게 정리시키는 이야기는 AI에게 오늘의 브리핑을 만들게 하는 글에도 썼습니다. 무인으로 돌릴 때의 권한 문제는 claude -p에서 MCP가 거부되는 원인을 다룬 글이 가까운 주제입니다.

흔한 실수와 함정

걸려 넘어지기 쉬운 점을 나열해 둡니다.

두 번째는 공식 문서에서도 분명하게 주의를 주고 있습니다. 비용이나 대기 시간을 줄이고 싶을 때는 상한을 낮추기보다 사고를 낮추라는 안내입니다. 상한을 조이면 응답이 끊기는 원인이 됩니다.

제가 밟은 것은 첫 번째와 다섯 번째였습니다. API 이용과 앱 버전의 유료 플랜은 별개의 이야기입니다. 앱 쪽 요금은 Google AI Pro의 기능과 요금을 정리한 글에 정리해 두었습니다.

시작하기 전에 확인할 것

비슷한 구조를 만드는 분을 위해 확인 항목을 정리했습니다.

세 번째와 여섯 번째가 특히 효과적이라고 생각합니다. 빈 응답과 만들어진 값은 둘 다 조용히 통과해 버리기 때문입니다.

자주 묻는 질문

Q. Gemini API의 응답이 비어 있을 때 가장 먼저 무엇을 보나요?

finishReason을 보는 것이 좋다고 생각합니다. MAX_TOKENS라면 지정된 최대 토큰 수에 도달한 것입니다. 함께 thoughtsTokenCount를 보면 사고에 쓰인 양을 알 수 있습니다.

Q. thinkingBudget을 0으로 할 수 없는 모델이 있나요?

공식 표에서는 2.5 Pro는 사고를 끌 수 없다고 되어 있습니다. 범위는 128~32768입니다. Gemini 3 계열은 thinkingLevel로 지정하는 형태이며, 완전한 사고 끄기를 지원하지 않는 모델도 있습니다.

Q. gemini-2.5-flash의 thinkingBudget 범위는 어떻게 되나요?

공식 표에서는 0~24576입니다. 지정하지 않으면 동적 사고가 됩니다. 0으로 끄기, -1로 동적 사고라는 지정입니다.

Q. 사고 토큰에도 요금이 부과되나요?

부과됩니다. 요금 페이지에는 출력 요금이 “사고 토큰 포함”이라고 적혀 있습니다. 상한에 도달해 출력이 비어 있어도 생성된 사고 몫은 과금된다고 합니다.

Q. maxOutputTokens를 크게 하면 해결되나요?

상한에 닿아서 끊기는 것이라면 여유를 두는 것도 한 가지 방법이라고 생각합니다. 다만 사고가 많은 채로는 비용과 대기 시간이 늘어납니다. 공식 문서는 사고 설정을 낮추는 방법을 안내하고 있습니다.

Q. 구조화 출력으로 하면 내용의 오류를 막을 수 있나요?

막을 수 없습니다. 공식 문서에는 보장되는 것은 구문상 올바른 JSON까지라고 적혀 있습니다. 값의 의미가 올바른지는 보장되지 않습니다. 앱 쪽에서 검증하는 처리가 필요합니다.

Q. 몇 건씩 나누는 것이 좋나요?

정해진 정답은 없다고 생각합니다. 기사 길이와 출력 형태에 따라 달라지기 때문입니다. 저는 10건을 5건씩으로 했더니 통과했지만, 이것은 제 용도에서의 결과입니다.

Q. 사고를 끄면 판정의 질이 떨어지지 않나요?

작업 내용에 따라 다르다고 생각합니다. 공식 문서에서는 분류나 사실 추출을 낮은 사고로 충분한 예로 들고 있습니다. 저는 질의 변화를 숫자로 비교하지 않았으니, 신경 쓰이는 분은 가지고 있는 기사로 시험해 보는 것이 좋아 보입니다.

참고한 공식 정보

정리

빈 채로 돌아온 이유는 사고에도 출력 한도가 쓰이기 때문이었습니다. thinkingBudget을 0으로 하고 5건씩 나누었더니 통과했습니다.

그렇다고는 해도 설정으로 고칠 수 있는 것은 “돌아오느냐 아니냐”까지입니다. 돌아온 내용이 맞는지는 따로 확인해야 했습니다. 마감일을 본문과 대조하는 후처리는 그것을 위한 장치입니다.

정형 처리에 생성형 AI를 넣고 계신 분은 빈 응답을 어떻게 다루고 있는지 한번 살펴보시면 어떨까요?

가입하지 않아도 100포인트를 받는 요금 시뮬레이션 구조로 수고를 줄였다면, 통신비도 라쿠텐 모바일에서 확인해 보기

누르면 라쿠텐 로그인 페이지가 열립니다. 로그인하면 캠페인 내용이 표시됩니다.

이 글에는 제휴 광고가 포함되어 있습니다. 이 사이트의 링크를 통해 상품·서비스에 신청하시면 제휴사로부터 보상을 받을 수 있습니다. 또한 운영자는 라쿠텐 그룹 소속 직원으로, 사원 추천 프로그램을 통해 보상을 받는 경우가 있습니다. 기사 내용과 평가는 광고 유무와 관계없이 운영자의 실제 경험과 조사를 바탕으로 작성했지만, 위 관계를 이해하신 후 읽어 주시기 바랍니다. 자세한 내용은 면책조항·제휴 링크 안내를 참고해 주세요. 면책조항·제휴 링크 안내

이 글에는 기계 번역이 포함되어 있습니다. 정확한 조건은 라쿠텐 모바일 공식 사이트의 다국어 페이지에서 확인해 주세요.

라쿠텐 모바일의 통신 지역·전파 상황이 궁금하신 분은, 공식 전파 개선·조사 요청 양식 을 통해 문의하실 수 있습니다.

ABOUT THE AUTHOR
まさきん

라쿠텐 그룹 근무·디지털 마케터(FP 자격 보유)

40대 초반, 맞벌이·네 자녀의 아빠. 라쿠텐 그룹에서 디지털 마케터로 근무하면서, 재무설계사(FP) 자격을 활용해 가계 관리와 자산 형성에도 힘쓰고 있다.

프로필 보기

관련 글

RELATED
Gemini(Google AI Pro) 패밀리 공유는 가족 5명까지. 설정 절차와 범위 AI 활용

Gemini(Google AI Pro) 패밀리 공유는 가족 5명까지. 설정 절차와 범위

Google AI Pro는 관리자 외에 가족 5명까지 공유할 수 있습니다. Gemini 앱과 저장용량은 공유되고 YouTube Premium Lite는 관리자만. Flow 한도는 가족이 나눠 씁니다. 설정 절차와 자녀 계정 처리를 공식 도움말로 정리했습니다.

2026.10.13 · 읽는 시간 약 13분
AI 구독 청구일과 가계부가 어긋나는 3가지 이유|Claude는 업그레이드하면 청구일이 바뀐다 AI 활용

AI 구독 청구일과 가계부가 어긋나는 3가지 이유|Claude는 업그레이드하면 청구일이 바뀐다

Claude는 월 중간에 Max로 올리면 청구 주기가 리셋되어 그날이 새로운 청구일이 됩니다. 달러 결제의 엔화 환산은 카드사에 데이터가 도착한 시점에 정해지고, 명세와 가계부 반영은 며칠 늦습니다. 영수증 메일을 기준으로 월을 정하는 5단계를 정리했습니다.

2026.10.13 · 읽는 시간 약 14분
freee 회계의 미처리 내역을 월 1회 대사 작업으로. 매월 5일 7:30·3구분·상한 15건으로 사람에게 넘기는 설계 AI 활용

freee 회계의 미처리 내역을 월 1회 대사 작업으로. 매월 5일 7:30·3구분·상한 15건으로 사람에게 넘기는 설계

freee 회계의 미처리 내역이 18건 정도, 주간 확인 6번 동안 움직이지 않은 채 남아 있었습니다. 매월 5일 아침 7:30에 집 Mac에서 돌리는 대사 작업의 설계와, 확정할 수 있는 분은 월 1건, 망설여지는 내역은 1건씩 상한 15건으로 사람에게 넘기는 기준을 정리합니다.

2026.10.12 · 읽는 시간 약 15분
라쿠텐 모바일로 전환 시 최대 14,000포인트 가입하지 않아도 100포인트를 받는 요금 시뮬레이션 →
지금 신청하기 →