단일 Gemini API 호출로 구글 검색·지도·맞춤 함수 통합하는 법
2026년 3월 구글이 발표한 Gemini API 툴링 업데이트를 활용해 구글 검색과 구글 지도, 그리고 사용자 정의 함수 호출을 단일 API 요청에 결합하는 방법을 다루는 튜토리얼입니다. 컨텍스트 순환(Context Circulation), 병렬 툴 ID, 멀티스텝 에이전틱 체인을 통해 이전 툴 호출과 응답을 유지하고 실시간 위치 데이터를 애플리케이션에 통합하는 방법을 보여줍니다. 빌링 설정 없이 무료로 실행 가능한 모델(gemini-3-flash-preview, gemini-2.5-flash)을 사용하여 5개의 실습 데모를 단계별로 제공합니다.
에디터 추천 | 에이전틱 AI | 소프트웨어 엔지니어링 | 스태프 | 튜토리얼
이 튜토리얼에서는 구글이 2026년 3월에 발표한 최신 Gemini API 툴링 업데이트, 특히 단일 API 요청에서 Google Search와 Google Maps 같은 내장 툴을 사용자 정의 함수 호출과 결합할 수 있는 기능을 살펴봅니다. 핵심 툴 결합 기능으로 시작해 완전한 멀티 툴 에이전틱 체인으로 끝나는 다섯 가지 실습 데모를 순차적으로 구성했습니다. 이 과정에서 컨텍스트 순환(Context Circulation)이 여러 턴에 걸쳐 모든 툴 호출과 응답을 보존하여 모델이 이전 출력을 기반으로 추론하는 방법, 고유한 툴 응답 ID(Tool Response ID)를 통해 병렬 함수 호출을 정확한 결과에 매핑하는 방법, 그리고 Google Maps 그라운딩(Grounding)이 실시간 위치 데이터를 애플리케이션에 가져오는 방법을 시연합니다. 툴 결합 기능에는 gemini-3-flash-preview를, Maps 그라운딩에는 gemini-2.5-flash를 사용하므로 빌링 설정 없이 모든 것을 실행할 수 있습니다.
코드 복사 완료. 다른 브라우저를 사용하세요.
[파이썬 설치 및 임포트 코드] import subprocess, sys subprocess.check_call([sys.executable, "-m", "pip", "install", "-qU", "google-genai"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
import getpass, json, textwrap, os, time from google import genai from google.genai import types
if "GOOGLE_API_KEY" not in os.environ: os.environ["GOOGLE_API_KEY"] = getpass.getpass("Enter your Gemini API key: ")
client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) TOOL_COMBO_MODEL = "gemini-3-flash-preview" MAPS_MODEL = "gemini-2.5-flash" DIVIDER = "=" * 72
[유틸리티 함수들] def heading(title: str): print(f"\n{DIVIDER}") print(f" {title}") print(DIVIDER)
def wrap(text: str, width: int = 80): for line in text.splitlines(): print(textwrap.fill(line, width=width) if line.strip() else "")
def describe_parts(response): parts = response.candidates[0].content.parts fc_ids = {} for i, part in enumerate(parts): prefix = f" Part {i:2d}:" if hasattr(part, "tool_call") and part.tool_call: tc = part.tool_call print(f"{prefix} [toolCall] type={tc.tool_type} id={tc.id}") if hasattr(part, "tool_response") and part.tool_response: tr = part.tool_response print(f"{prefix} [toolResponse] type={tr.tool_type} id={tr.id}") if hasattr(part, "executable_code") and part.executable_code: code = part.executable_code.code[:90].replace("\n", " ↵ ") print(f"{prefix} [executableCode] {code}...") if hasattr(part, "code_execution_result") and part.code_execution_result: out = (part.code_execution_result.output or "")[:90] print(f"{prefix} [codeExecResult] {out}") if hasattr(part, "function_call") and part.function_call: fc = part.function_call fc_ids[fc.name] = fc.id print(f"{prefix} [functionCall] name={fc.name} id={fc.id}") print(f" └─ args: {dict(fc.args)}") if hasattr(part, "text") and part.text: snippet = part.text[:110].replace("\n", " ") print(f"{prefix} [text] {snippet}...") if hasattr(part, "thought_signature") and part.thought_signature: print(f" └─ thought_signature present ✓") return fc_ids
[데모 1 시작] heading("DEMO 1: Combine Google Search + Custom Function in One Request") print(""" 이 데모는 핵심 신규 기능을 보여줍니다: 내장 툴(Google Search)과 사용자 정의 함수 선언을 단일 API 호출에서 함께 전달하는 것입니다. Gemini는 다음과 같이 동작합니다: 턴 1 → 웹에서 실시간 정보를 검색한 후, 날씨 데이터를 가져오기 위해 사용자 정의 함수를 요청합니다. 턴 2 → 우리가 함수 응답을 제공하면, Gemini가 모든 것을 종합합니다.
핵심 포인트: • google_search와 function_declarations가 동일한 Tool 객체에 들어갑니다. • include_server_side_tool_invocations는 반드시 True여야 합니다 (ToolConfig에서). • 후속 턴에서 모든 파트(thought_signatures 포함)를 반환해야 합니다. """)
[함수 선언] get_weather_func = types.FunctionDeclaration( name="getWeather", description="Gets the current weather for a requested city.", parameters=types.Schema( type="OBJECT", properties={ "city": types.Schema( type="STRING", description="The city and state, e.g. Utqiagvik, Alaska", ), }, required=["city"], ), )
print("▶ Turn 1: Google Search + getWeather 툴과 함께 프롬프트 전송 중...\n") response_1 = client.mo...