Gemini 3.8 Flash 함수 호출 루프 구현 가이드
Gemini 3.8 Flash는 2026년 9월 2일 출시되었으며, Google은 이 모델을 “도구를 반복적으로 호출”하도록 설계했습니다. 어려운 작업에서 한 번에 추측하는 대신 도구를 호출하고, 결과를 확인한 뒤 다시 호출하는 방식입니다. 에이전트에는 희소식이지만 3.7 Flash에 맞춰 도구 루프를 조정한 사용자에게는 새로운 과제가 생겼습니다. 특히 두 가지 API 세부 사항이 중요합니다. 모든 함수 결과에는 call_id와 name이 모두 필요하고, 이제 루프의 기본 구현에는 generateContent보다 Interactions API가 권장됩니다.
이 가이드에서는 Interactions API의 전체 도구 호출 흐름, 레거시 generateContent 방식, 3.8 Flash가 더 많은 턴과 토큰을 사용하는 이유, 그리고 매일 실행 가능한 테스트 설정을 설명합니다. 테스트에서는 도구 백엔드를 모의하고 두 턴을 연결하며 call_id 왕복을 검증합니다.
모델 개요가 먼저 필요하다면 Gemini 3.8 Flash란 무엇인가부터 확인하세요. 아래 필드 이름은 Google의 함수 호출 문서를 기준으로 작성했습니다.
여기의 모든 요청은 JSON을 사용하는 일반 HTTP 요청이므로, 애플리케이션 코드에 넣기 전에 Apidog에서 구축하고 디버깅할 수 있습니다.
Gemini 3.8 Flash 함수 호출 요약
| 항목 | Gemini 3.8 Flash |
|---|---|
| 모델 ID |
gemini-3.8-flash — 안정 버전이며 프리뷰 접미사 없음 |
| 기본 API | Interactions API (POST /v1beta/interactions); generateContent도 레거시 방식으로 완벽하게 지원 |
| 도구 선언 | tools: [{"type": "function", "name", "description", "parameters"}] |
| 모델 호출 |
id, name, arguments를 포함하는 function_call 단계 |
| 사용자 응답 |
call_id와 name이 모두 필요하며 previous_interaction_id를 포함하는 function_result
|
| 사고 수준 |
thinking_level: low / medium(기본값) / high; minimal은 유효성 검사 오류 발생 |
| 도구 사용 점수 | Tau3-Banking 45% — 3.7 Flash 대비 12포인트 상승(Artificial Analysis, 독립 평가) |
| 토큰 비용 | Artificial Analysis 인덱스 기준 작업당 약 48k 출력 토큰 — 3.7 Flash 대비 30% 증가 |
| 가격 | 2026년 12월 31일까지 입력 100만 토큰당 $0.75, 출력 100만 토큰당 $3.75; 사고 토큰은 출력으로 청구 |
1단계: 도구 선언
Interactions API의 도구는 평면 객체입니다.
-
type:function -
name: 함수 이름 -
description: 모델이 호출 시점을 결정할 때 읽는 설명 -
parameters: JSON Schema
설명은 구체적으로 작성하세요. 예를 들어 “주문 ID로 현재 배송 상태 조회”는 적절하지만 “주문 도우미”는 예측하기 어려운 시점에 호출될 수 있습니다.
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-[REDACTED CREDENTIAL] \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3.8-flash",
"input": "Where is order A1029 right now?",
"generation_config": {"thinking_level": "low"},
입니다.
## 2단계: `function_call` 단계 읽기
Interactions API는 단일 메시지가 아니라 상호작용 자체의 `id`와 실행 단계 목록을 반환합니다. 단계에는 모델의 사고, 도구 호출, 최종 답변이 포함될 수 있습니다. 모델이 도구가 필요하다고 판단하면 `model_output` 대신 `function_call` 단계가 반환됩니다.
json
{
"type": "function_call",
"id": "call_8f2d...",
"name": "get_order_status",
"arguments": {"order_id": "A1029"}
}
세 필드를 모두 처리해야 합니다.
- `id`: 다음 요청에서 `call_id`로 다시 보낼 호출 핸들
- `name`: 실행할 함수 이름
- `arguments`: 이미 파싱된 JSON
실행 전에 자체 규칙으로 `arguments`를 검증하세요. 모델은 선언한 스키마는 따르지만, 주문 ID가 반드시 5자리여야 한다는 비즈니스 규칙까지 알지는 못합니다.
응답 상단의 상호작용 `id`도 저장하세요. 다음 턴에서 `previous_interaction_id`로 사용합니다.
## 3단계: `call_id`와 `name`으로 결과 반환
함수를 실행한 뒤 `input`이 `function_result`인 두 번째 요청을 보냅니다. Gemini 3.8 Flash에서는 `call_id`와 `name`이 모두 필수입니다. 둘 중 하나라도 빠지면 요청이 실패합니다.
bash
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-[REDACTED CREDENTIAL] \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3.8-flash",
"previous_interaction_id": "",
"input": [{
"type": "function_result",
"name": "get_order_status",
"call_id": "call_8f2d...",
"result": [{"type": "text", "text": "{\"status\":\"in_transit\",\"eta\":\"2026-09-05\"}"}]
}]
}'
`result`는 콘텐츠 파트 목록입니다. 텍스트 파트에서는 JSON을 문자열로 전달합니다.
`previous_interaction_id`가 이전 턴을 가리키므로 서버는 원래 프롬프트, 도구 선언, 모델의 추론을 이미 보유하고 있습니다. 이 데이터를 다시 보낼 필요가 없습니다.
두 번째 응답도 단계 목록입니다.
- `model_output`으로 끝나면 작업이 완료됩니다.
- SDK는 최종 텍스트를 `interaction.output_text`로 노출합니다.
- 또 다른 `function_call`이 있으면 해당 함수를 실행하고 다시 결과를 반환합니다.
이 반복이 전체 도구 루프 패턴입니다.
Python에서는 다음과 같은 흐름을 사용합니다.
python
client.interactions.create(
model="gemini-3.8-flash",
input=...,
...
)
두 번째 `create` 호출에서는 `previous_interaction_id`와 `function_result` 목록을 `input`으로 전달합니다. 엔드포인트, 키, 스트리밍, 토큰 사용량 확인 방법은 [Gemini 3.8 Flash API 사용법](https://apidog.com/kr/blog/how-to-use-gemini-3-8-flash-api?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation)에서 확인할 수 있습니다.
## 레거시 `generateContent` 대안
기존 Gemini 코드는 여전히 `models/gemini-3.8-flash:generateContent`를 많이 사용합니다. Google은 이 API를 “완벽하게 지원”하며 지원 종료 날짜도 없다고 설명합니다.
용어는 다르지만 계약은 같습니다.
- 도구: `functionDeclarations` 아래에 선언
- 모델 호출: `functionCall` 파트
- 사용자 결과: `functionResponse` 파트
레거시 형식에서 모델의 `functionCall` 파트는 `id`를 포함합니다. 사용자 `functionResponse` 파트는 `name`, `response`와 함께 동일한 값을 자체 `id` 필드에 에코해야 합니다. 즉, Interactions API의 `call_id`와 필드 이름은 다르지만 호출 ID와 함수 이름을 왕복시키는 동일한 계약입니다. Google의 Gemini 3 지침에 따라 `id`와 `name`은 모두 필요합니다.
실무적으로 중요한 차이는 두 가지입니다.
### 1. 상태 관리
`generateContent`는 상태 비저장 방식입니다. 애플리케이션이 대화를 직접 관리하고, 모델의 `functionCall` 파트와 반환된 모든 사고 서명을 포함한 전체 `contents` 기록을 매 턴 다시 보내야 합니다.
### 2. 사고 수준 설정
Interactions API의 다음 설정 대신:
json
{"generation_config": {"thinking_level": "low"}}
`generateContent`에서는 다음과 같이 설정합니다.
json
{"generationConfig": {"thinkingConfig": {"thinkingLevel": "low"}}}
사고 토큰은 응답의 `usageMetadata.thoughtsTokenCount`에 표시되며 출력 토큰으로 청구됩니다.
새 프로젝트에서 두 API 중 하나를 선택한다면 Interactions API를 권장합니다. 서버 측 상태를 사용하면 기록, 사고 서명, `call_id`가 누락되는 버그를 줄일 수 있습니다.
## 3.8 Flash의 반복 호출과 루프 제한
Google의 [출시 게시물](https://blog.google/innovation-and-ai/models-and-research/gemini-models/3-8-flash-and-3-8-flash-cyber/)에 따르면 이 모델은 복잡한 작업에서 “추가 추론 단계를 실행하고 도구를 반복적으로 호출”합니다. 더 작은 추론 단계로 작업을 나누고 결과를 확인하는 방식입니다. Google은 또한 이 모델이 복잡한 작업에서 더 오래 실행되고 더 많은 토큰을 사용할 수 있도록 설계되었다고 설명합니다.
[Artificial Analysis](https://artificialanalysis.ai/articles/gemini-3-8-flash)는 작업당 약 48k 출력 토큰을 측정했습니다. 이는 3.7 Flash 대비 30% 증가한 수치입니다. 동일한 토큰당 가격을 기준으로 한 작업당 비용은 다음과 같습니다.
- `high`: $0.58 — 3.7 Flash는 $0.40
- `medium`: $0.41
- `low`: $0.24
도구 루프에서는 작업당 `function_call` 단계가 더 많아질 수 있습니다. 장점도 분명합니다. Artificial Analysis의 도구 사용 평가 Tau3-Banking에서 3.8 Flash는 45%를 기록해 3.7 Flash보다 12포인트 상승했습니다.
반면 상한이 없는 루프는 8월보다 오래 실행될 수 있습니다. 다음 네 가지 제어 방법을 적용하세요.
1. **하니스에 최대 턴 수를 설정합니다.**
작업별 `function_call` 단계 수를 세고 제한에 도달하면 중단합니다. 조회 작업에는 6~10회가 합리적인 시작점이며, 에이전트 코딩에는 더 높은 값이 필요할 수 있습니다. 제한에 도달하면 도구 없이 최종 턴을 보내거나 사용자에게 오류를 반환하세요. 모델이 스스로 루프를 제한한다고 가정하지 마십시오.
2. **경로별 `thinking_level`을 사용합니다.**
조회와 단일 홉 도구에는 `low`, 다단계 작업에는 `medium`(기본값), 추가 검증이 필요한 경우에만 `high`를 사용합니다. `minimal`은 보내지 마세요. 3.8 Flash에서는 유효성 검사 오류가 발생합니다.
3. **요청과 작업 양쪽에 타임아웃을 설정합니다.**
Gemini 호출에는 요청당 타임아웃을, 전체 루프에는 작업당 시간 제한을 적용합니다. Artificial Analysis 측정에서 고수준 추론 실행은 작업당 평균 2.5분, `low`는 0.8분이었습니다.
4. **도구를 멱등적으로 설계합니다.**
반복적인 모델은 같은 도구를 재시도할 수 있습니다. `get_order_status`처럼 조회 함수는 두 번 호출해도 안전해야 합니다. 환불이나 발송처럼 부작용이 있는 작업은 확인 단계를 요구하세요.
추가 턴을 감당할 예산이 없다면 [3.7에서 3.8 Flash 마이그레이션 가이드](https://apidog.com/kr/blog/gemini-3-7-to-3-8-flash-migration-guide?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation)를 참고해 구성 플래그 뒤에 3.7 Flash를 유지할 수 있습니다. 3.7 Flash도 계속 완벽하게 지원됩니다.
## 사고 서명, 병렬 호출, 구조화된 출력
### 사고 서명
Gemini 3 모델은 추론에 사고 서명을 첨부합니다.
기본 저장형 Interactions 흐름에서는 `previous_interaction_id`가 이를 처리합니다. `store: false`를 사용하거나 `generateContent`를 사용하는 상태 비저장 구성에서는 모든 파트 유형에 대해 수신한 사고 블록과 서명을 그대로 다시 보내야 합니다.
사고 서명을 다음과 같이 처리하지 마세요.
- 잘라내기
- 순서 변경
- 재직렬화
서명은 불투명한 값이며 편집하면 무효화됩니다. 저장형과 상태 비저장형 방식의 장단점은 [Interactions API 문서](https://ai.google.dev/gemini-api/docs/interactions)에서 확인할 수 있습니다.
### 병렬 호출
응답은 단계 목록이므로 모델이 서로 독립적인 조회를 원할 때 여러 `function_call` 단계가 반환될 수 있습니다.
Google의 [함수 호출 문서](https://ai.google.dev/gemini-api/docs/generate-content/function-calling)에 따르면 Gemini 3 모델은 각 호출에 고유한 ID를 반환하며 결과는 어떤 순서로든 반환할 수 있습니다.
따라서 다음 규칙을 지키세요.
- 동일한 `input` 배열에서 각 호출에 하나의 `function_result`를 반환합니다.
- 각 결과에 올바른 `call_id`와 일치하는 `name`을 넣습니다.
- `name`만으로 호출을 매칭하지 않습니다.
- 같은 함수가 두 번 호출되어도 두 호출에는 서로 다른 ID가 있어야 합니다.
### 구조화된 출력
3.8 Flash는 함수 호출과 구조화된 출력을 동시에 지원합니다. 도구는 루프에 사용하고 최종 답변에는 JSON Schema를 적용하는 방식이 깔끔합니다. 그러면 루프를 종료하는 `model_output`도 산문이 아니라 기계가 읽을 수 있는 JSON이 됩니다.
호출을 유도하기 위해 더미 도구를 선언하거나 `arguments`를 가짜로 읽는 방식은 사용하지 마세요. 모델이 호출할 도구가 없다고 판단하는 순간 루프가 종료될 수 있습니다.
위 내용은 모델이 선언된 함수를 통해 시스템과 통신하는 경우를 전제로 합니다. Google은 3.8 Flash용 Computer use (Preview)도 제공합니다. 화면 제어보다 구조화된 API가 적합한지 비교하려면 [컴퓨터 사용 대 구조화된 API](https://apidog.com/kr/blog/computer-use-vs-structured-apis?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation)를 참고하세요.
## Apidog에서 도구 루프 테스트하기
도구 루프에는 세 가지 주요 실패 지점이 있습니다.
1. 도구 선언
2. ID 왕복
3. 최종 답변
실제 백엔드에 영향을 주지 않고 [Apidog](https://apidog.com?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation)에서 세 가지를 모두 검증할 수 있습니다.
### 1. 도구 백엔드 모의
`GET /orders/{order_id}` 엔드포인트를 정의하고 모의 서버를 실행합니다. 다음과 같은 고정 응답을 사용하세요.
json
{"status": "in_transit", "eta": "2026-09-05"}
모든 실행이 동일한 입력을 받게 하면 최종 답변의 변화가 데이터베이스가 아니라 모델 동작 때문인지 확인할 수 있습니다.
- 테스트 환경: 하니스가 모의 URL을 호출
- 프로덕션 환경: 하니스가 실제 서비스 URL을 호출
### 2. 두 턴 연결
`GEMINI_API_KEY`를 환경 변수로 저장하고 `x-goog-api-key` 헤더에서 `{{GEMINI_API_KEY}}`로 참조합니다. 그런 다음 다음 세 단계를 시나리오로 구성합니다.
- **단계 A:** 프롬프트와 `get_order_status` 선언으로 `/v1beta/interactions`에 POST 요청을 보냅니다. 상호작용 `id`, `function_call` 단계의 `id`와 `name`, `arguments.order_id`를 변수로 추출합니다.
- **단계 B:** `{{order_id}}`를 사용해 모의 엔드포인트에 GET 요청을 보냅니다. 이 단계가 함수 실행을 대신합니다.
- **단계 C:** `call_id`를 `{{call_id}}`, `name`을 `{{tool_name}}`, `previous_interaction_id`를 `{{interaction_id}}`로 설정합니다. 단계 B의 본문은 텍스트 파트로 넣어 `function_result`를 POST합니다.
### 3. 핵심 검증
다음 조건을 테스트에 추가하세요.
- 단계 A가 HTTP 200을 반환합니다.
- 단계 A의 단계 목록에 `type: "function_call"`이 포함됩니다.
- 해당 단계의 `name`이 `get_order_status`와 일치합니다.
- 추출된 `arguments.order_id`가 `A1029`인지 확인합니다. 이는 모델이 프롬프트를 해석하고 스키마를 준수했음을 보여줍니다.
- 단계 C가 HTTP 200을 반환합니다.
- 단계 C가 두 번째 `function_call` 없이 `type: "model_output"` 단계로 끝나는지 확인합니다. 이는 `call_id`와 `name`이 수락되어 한 번의 왕복으로 루프가 닫혔다는 뜻입니다.
- 최종 텍스트에 `in_transit`이 포함되는지 확인합니다. 모델이 추측이 아니라 도구 결과를 사용했는지 검증할 수 있습니다.
- `generateContent` 시나리오에서는 각 `thinking_level`에 대해 `usageMetadata.thoughtsTokenCount` 상한을 추가합니다. “더 열심히 작동하는” 동작으로 인한 비용 증가가 청구서에 반영되기 전에 감지할 수 있습니다.
시나리오는 매일 실행하도록 예약하세요. 모델 동작은 조용한 업데이트에 따라 달라질 수 있으며, 지난주에는 한 번의 왕복으로 끝나던 루프가 두 번의 왕복을 요구할 수도 있습니다.
다단계 검증 방법은 [AI 에이전트 API 테스트 가이드](https://apidog.com/kr/blog/how-to-test-ai-agents-api?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation)에서 더 자세히 다룹니다. 비용을 지불하기 전에 [Apidog를 다운로드](https://apidog.com/download?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation)해 무료 계층에서 시나리오를 구축할 수도 있습니다.
## 자주 묻는 질문
### Gemini 3.8 Flash에서 `call_id`는 필수인가요?
예.
- Interactions API의 모든 `function_result`에는 `call_id`와 `name`이 필요합니다.
- `generateContent`의 모든 `functionResponse`에는 호출의 `id`와 `name`이 필요합니다.
이름만 보내던 기존 코드는 Gemini 3 모델에서 실패합니다.
### 도구 루프가 3.7보다 3.8 Flash에서 더 많은 턴을 실행하는 이유는 무엇인가요?
의도된 설계입니다. Google은 모델이 도구를 반복적으로 호출하고 더 오래 실행되며 복잡한 작업에 더 많은 토큰을 사용할 수 있다고 설명합니다.
하니스에서 최대 턴 수를 제한하고 `thinking_level`을 낮추세요. 수준별 측정 비용은 [사고 수준 가이드](https://apidog.com/kr/blog/gemini-3-8-flash-thinking-levels?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation)에서 확인할 수 있습니다.
### 함수 호출에 여전히 `generateContent`를 사용할 수 있나요?
예. Google은 `generateContent`를 레거시 API로 분류하지만 지원 종료 날짜 없이 완벽하게 지원한다고 말합니다.
다만 사고 서명을 포함한 전체 기록을 직접 관리해야 합니다. 이 API에서는 호출 ID가 `id`로 표시되며 `id`와 `name`을 모두 전달해야 합니다.
### `thinking_level: "minimal"`이 도구와 함께 작동하나요?
아니요. 3.8 Flash에서는 유효성 검사 오류가 발생합니다. `low`를 사용하세요.
### 도구 사용량이 많은 작업의 비용은 얼마인가요?
2026년 12월 31일까지 가격은 다음과 같습니다.
- 입력: 100만 토큰당 $0.75
- 출력: 100만 토큰당 $3.75
- 사고 토큰: 출력으로 청구
Artificial Analysis는 자체 인덱스에서 작업당 비용을 다음과 같이 측정했습니다.
- `high`: $0.58
- `medium`: $0.41
- `low`: $0.24
실제 비용은 작업에 따라 달라지므로 토큰 수를 직접 확인하고 측정해야 합니다.
## 상한선을 정해 루프 배포하기
Gemini 3.8 Flash의 함수 호출 계약은 다음과 같습니다.
1. 도구를 선언합니다.
2. `function_call` 단계를 읽습니다.
3. `previous_interaction_id` 아래에 `call_id`와 `name`을 모두 포함한 `function_result`를 반환합니다.
3.8 Flash에서 달라진 점은 모델이 더 적극적으로 반복 호출한다는 것입니다. 따라서 프로덕션 배포 전 하니스에 다음을 반드시 추가하세요.
- 최대 턴 수
- 경로별 `thinking_level`
- 요청 및 작업 타임아웃
- 멱등 도구와 부작용 확인 단계
백엔드를 모의하고, 두 턴을 연결하고, ID 왕복을 검증한 뒤 테스트를 예약하세요.
Google의 [Gemini 3.8 Flash의 새로운 기능](https://ai.google.dev/gemini-api/docs/latest-model)에는 마이그레이션 노트가 있으며, [Gemini 3.8 Flash 개요](https://apidog.com/kr/blog/what-is-gemini-3-8-flash?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation)에서는 모델에 관한 추가 정보를 확인할 수 있습니다.
Top comments (0)