Google Search 접지(Grounding)

Google Search 접지(Grounding)

Google Search 접지는 Gemini 모델을 실시간 웹 콘텐츠에 연결하고 모든 지원 언어에서 동작해요. 이를 통해 Gemini는 지식 컷오프 너머에서도 더 정확한 답변을 제공하고 검증 가능한 출처를 인용할 수 있어요.

접지는 다음을 할 수 있는 애플리케이션을 만드는 데 도움을 줘요.

  • 사실 정확성 높이기: 응답을 실세계 정보에 기반해 모델 환각을 줄여요.
  • 실시간 정보 접근: 최근 사건·주제에 대한 질문에 답해요.
  • 인용 제공: 모델 주장의 출처를 보여줘 사용자 신뢰를 구축해요.
from google import genai
from google.genai import types

client = genai.Client()

grounding_tool = types.Tool(
    google_search=types.GoogleSearch()
)

config = types.GenerateContentConfig(
    tools=[grounding_tool]
)

response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents="Who won the euro 2024?",
    config=config,
)

print(response.text)
import { GoogleGenAI } from "@google/genai";

const ai = new GoogleGenAI({});

const groundingTool = {
  googleSearch: {},
};

const config = {
  tools: [groundingTool],
};

const response = await ai.models.generateContent({
  model: "gemini-3.8-flash",
  contents: "Who won the euro 2024?",
  config,
});

console.log(response.text);
curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:generateContent" \
  -H "x-goog-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -X POST \
  -d '{
    "contents": [
      {
        "parts": [
          {"text": "Who won the euro 2024?"}
        ]
      }
    ],
    "tools": [
      {
        "google_search": {}
      }
    ]
  }'

Search tool notebook으로 더 자세히 배울 수 있어요.

출처: 원문

본문

Google Search 접지 작동 방식

google_search 도구를 활성화하면 모델이 검색·처리·인용의 전체 워크플로를 자동으로 처리해요.

  1. 사용자 프롬프트: 애플리케이션이 google_search 도구를 활성화한 채 사용자 프롬프트를 Gemini API에 보내요.
  2. 프롬프트 분석: 모델이 프롬프트를 분석하고 Google Search가 답을 개선할 수 있는지 판단해요.
  3. Google Search: 필요하면 모델이 하나 이상의 검색 쿼리를 자동 생성해 실행해요.
  4. 검색 결과 처리: 모델이 검색 결과를 처리하고 정보를 종합해 응답을 구성해요.
  5. 접지된 응답: API가 검색 결과에 근거한 최종 사용자 친화적 응답을 반환해요. 이 응답에는 모델의 텍스트 답과 함께 검색 쿼리·웹 결과·인용을 담은 groundingMetadata가 포함돼요.

접지 응답 이해하기

응답이 성공적으로 접지되면 groundingMetadata 필드가 포함돼요. 이 구조화된 데이터는 주장 검증과 애플리케이션에서 풍부한 인용 경험 구축에 필수적이에요.

{
  "candidates": [
    {
      "content": {
        "parts": [
          {
            "text": "Spain won Euro 2024, defeating England 2-1 in the final. This victory marks Spain's record fourth European Championship title."
          }
        ],
        "role": "model"
      },
      "groundingMetadata": {
        "webSearchQueries": [
          "UEFA Euro 2024 winner",
          "who won euro 2024"
        ],
        "searchEntryPoint": {
          "renderedContent": "<!-- HTML and CSS for the search widget -->"
        },
        "groundingChunks": [
          {"web": {"uri": "https://vertexaisearch.cloud.google.com.....", "title": "aljazeera.com"}},
          {"web": {"uri": "https://vertexaisearch.cloud.google.com.....", "title": "uefa.com"}}
        ],
        "groundingSupports": [
          {
            "segment": {"startIndex": 0, "endIndex": 85, "text": "Spain won Euro 2024, defeatin..."},
            "groundingChunkIndices": [0]
          },
          {
            "segment": {"startIndex": 86, "endIndex": 210, "text": "This victory marks Spain's..."},
            "groundingChunkIndices": [0, 1]
          }
        ]
      }
    }
  ]
}

Gemini API는 groundingMetadata와 함께 다음 정보를 반환해요.

  • webSearchQueries: 사용된 검색 쿼리 배열. 디버깅과 모델의 추론 과정 이해에 유용해요.
  • searchEntryPoint: 필수 Search Suggestions를 렌더링할 HTML과 CSS를 담아요. 전체 사용 요구사항은 Terms of Service에 상세히 나와 있어요.
  • groundingChunks: 웹 출처(uri와 title)를 담은 객체 배열.
  • groundingSupports: 모델 응답 text를 groundingChunks의 출처와 연결하는 청크 배열. 각 청크는 텍스트 segment(startIndex와 endIndex로 정의)를 하나 이상의 groundingChunkIndices에 연결해요. 인라인 인용 구축의 핵심이에요.

Google Search 접지는 URL context 도구와 함께 써서 공개 웹 데이터와 사용자가 제공한 특정 URL 모두에 응답을 근거 지을 수도 있어요.

인라인 인용으로 출처 표시하기

API는 구조화된 인용 데이터를 반환하므로 사용자 인터페이스에서 출처를 표시하는 방식을 완전히 제어할 수 있어요. groundingSupports와 groundingChunks 필드로 모델의 진술을 출처에 직접 연결할 수 있어요. 인라인·클릭 가능 인용이 있는 응답을 만드는 일반적인 처리 패턴은 다음과 같아요.

def add_citations(response):
    text = response.text
    supports = response.candidates[0].grounding_metadata.grounding_supports
    chunks = response.candidates[0].grounding_metadata.grounding_chunks

    # Sort supports by end_index in descending order to avoid shifting issues when inserting.
    sorted_supports = sorted(supports, key=lambda s: s.segment.end_index, reverse=True)

    for support in sorted_supports:
        end_index = support.segment.end_index
        if support.grounding_chunk_indices:
            # Create citation string like [1](link1)[2](link2)
            citation_links = []
            for i in support.grounding_chunk_indices:
                if i < len(chunks):
                    uri = chunks[i].web.uri
                    citation_links.append(f"[{i + 1}]({uri})")

            citation_string = ", ".join(citation_links)
            text = text[:end_index] + citation_string + text[end_index:]

    return text

# Assuming response with grounding metadata
text_with_citations = add_citations(response)
print(text_with_citations)
function addCitations(response) {
    let text = response.text;
    const supports = response.candidates[0]?.groundingMetadata?.groundingSupports;
    const chunks = response.candidates[0]?.groundingMetadata?.groundingChunks;

    // Sort supports by end_index in descending order to avoid shifting issues when inserting.
    const sortedSupports = [...supports].sort(
        (a, b) => (b.segment?.endIndex ?? 0) - (a.segment?.endIndex ?? 0),
    );

    for (const support of sortedSupports) {
        const endIndex = support.segment?.endIndex;
        if (endIndex === undefined || !support.groundingChunkIndices?.length) {
        continue;
        }

        const citationLinks = support.groundingChunkIndices
        .map(i => {
            const uri = chunks[i]?.web?.uri;
            if (uri) {
            return `[${i + 1}](${uri})`;
            }
            return null;
        })
        .filter(Boolean);

        if (citationLinks.length > 0) {
        const citationString = citationLinks.join(", ");
        text = text.slice(0, endIndex) + citationString + text.slice(endIndex);
        }
    }

    return text;
}

const textWithCitations = addCitations(response);
console.log(textWithCitations);

인라인 인용이 있는 새 응답은 다음과 같아요.

Spain won Euro 2024, defeating England 2-1 in the final.[1](https:/...), [2](https:/...), [4](https:/...), [5](https:/...) This victory marks Spain's record-breaking fourth European Championship title.[5]((https:/...), [2](https:/...), [3](https:/...), [4](https:/...)

가격

Gemini 3으로 Google Search 접지를 사용하면 모델이 실행하기로 결정한 각 검색 쿼리마다 프로젝트에 청구돼요. 모델이 단일 프롬프트에 답하기 위해 여러 검색 쿼리를 실행하기로 하면(예: 같은 API 호출 안에서 "UEFA Euro 2024 winner"와 "Spain vs England Euro 2024 final score"를 검색), 그 요청에서 도구 사용이 2회 청구로 계산돼요. 청구 목적으로 고유 쿼리를 셀 때 빈 웹 검색 쿼리는 무시해요. 이 청구 모델은 Gemini 3 모델에만 적용돼요. Gemini 2.5 이하 모델로 검색 접지를 쓰면 프로젝트에 프롬프트당 청구돼요.

자세한 가격은 Gemini API pricing 페이지를 참고하세요.

지원 모델

전체 능력은 model overview 페이지에서 확인할 수 있어요.

모델 Google Search 접지
Gemini 3.8 Flash ✔️
Gemini 3.7 Flash ✔️
Gemini 3.6 Flash ✔️
Gemini 3.5 Flash-Lite ✔️
Gemini 3.5 Flash ✔️
Gemini 3.1 Flash-Lite ✔️
Gemini 3.1 Flash Image Preview ✔️
Gemini 3.1 Pro Preview ✔️
Gemini 3 Pro Image Preview ✔️
Gemini 3 Flash Preview ✔️
Gemini 3.1 Flash-Lite Preview ✔️
Gemini 2.5 Pro ✔️
Gemini 2.5 Flash ✔️
Gemini 2.5 Flash-Lite ✔️
Gemini 2.0 Flash ✔️

참고: 옛 모델은 google_search_retrieval 도구를 사용해요. 모든 현재 모델에서는 예제처럼 google_search 도구를 쓰세요.

지원 도구 조합

Google Search 접지는 코드 실행, URL context, Google Maps 접지(Gemini 3.5 Flash 이상 모델에서 지원) 같은 다른 도구와 함께 써서 더 복잡한 사용 사례를 만들 수 있어요. Gemini 3 모델은 이런 내장 도구를 커스텀 도구(함수 호출)와 결합하는 것도 지원해요. tool combinations 페이지에서 자세히 알아보세요.

다음 단계

더 알아보기 (Learn more)