Place Autocomplete 데이터 API

Place Autocomplete Data API를 사용하면 장소 예상 검색어를 가져올 수 있습니다. 프로그래매틱 방식으로, 더 세밀하게 제어할 수 있는 맞춤설정된 자동 완성 환경을 만들기 위해 더 많이 표시할 수 있습니다. 이 가이드에서는 Place Autocomplete Data API: 사용자 기반의 자동 완성 요청 쿼리합니다.

다음 예는 간단한 자동 완성 통합을 보여줍니다. 검색어를 입력한 다음 원하는 결과를 선택합니다.

<ph type="x-smartling-placeholder"></ph>

Autocomplete 요청

자동 완성 요청은 쿼리 입력 문자열을 사용하여 장소 예상 검색어 목록을 반환합니다. 받는사람 자동 완성을 요청하려면 fetchAutocompleteSuggestions()를 호출합니다. 필요한 속성이 포함된 요청을 전달합니다. input 속성에는 검색할 문자열이 포함됩니다. 일반적인 애플리케이션에서는 이 값이 사용자가 검색어를 입력할 때 요청에는 sessionToken, 이는 청구 목적으로 사용됩니다.

다음 스니펫은 요청 본문을 만들고 세션 토큰을 추가한 다음 fetchAutocompleteSuggestions(): PlacePrediction

// Add an initial request body.
let request = {
  input: "Tadi",
  locationRestriction: {
    west: -122.44,
    north: 37.8,
    east: -122.39,
    south: 37.78,
  },
  origin: { lat: 37.7893, lng: -122.4039 },
  includedPrimaryTypes: ["restaurant"],
  language: "en-US",
  region: "us",
};
// Create a session token.
const token = new AutocompleteSessionToken();

// Add the token to the request.
// @ts-ignore
request.sessionToken = token;

자동 완성 예상 검색어 제한

기본적으로 Place Autocomplete는 사용자 위치 근처의 예상 검색어에 편중된 모든 장소 유형을 표시하며 사용자가 선택한 장소의 사용 가능한 모든 데이터 필드를 가져옵니다. 결과를 제한하거나 상세 검색하여 더 관련성 높은 예상 검색어를 표시하려면 Place Autocomplete 옵션을 설정하세요.

결과를 제한하면 자동 완성 위젯이 제한 영역입니다. 일반적인 방법은 결과를 지도 경계로 제한하는 것입니다. 결과를 상세 검색하면 자동 완성 위젯이 지정된 지역 내 결과를 표시하지만 일부 일치 항목이 해당 지역을 벗어날 수 있습니다.

origin 속성을 사용하여 계산할 출발지를 지정합니다. 목적지까지의 최단 거리 거리. 이 값을 생략하면 거리가 반환되지 않습니다.

includedPrimaryTypes 사용 속성을 사용하여 최대 5개의 장소 유형을 지정할 수 있습니다. 유형을 지정하지 않으면 모든 유형의 장소가 반환됩니다.

API 참조 보기

장소 세부정보 가져오기

Place 반환 장소 예상 검색어 결과에서 객체를 반환합니다. 먼저 toPlace()를 호출합니다. 그런 다음 fetchFields()를 호출합니다. 결과 Place 객체에서 설정 (장소 예상 검색어의 세션 ID가 자동으로 포함됨)을 반환합니다. fetchFields()를 호출하면 자동 완성 세션을 사용합니다.

let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place.

await place.fetchFields({
  fields: ["displayName", "formattedAddress"],
});

const placeInfo = document.getElementById("prediction");

placeInfo.textContent =
  "First predicted place: " +
  place.displayName +
  ": " +
  place.formattedAddress;

세션 토큰

세션 토큰은 사용자 자동 완성 검색의 쿼리 및 선택 단계를 별도의 세션을 만들 수 없습니다. 사용자가 입력을 시작하면 세션이 시작됩니다. 사용자가 장소를 선택하고 장소 세부정보가 호출되면 세션이 종료됩니다.

새 세션 토큰을 만들어 요청에 추가하려면 AutocompleteSessionToken님, 그런 다음 sessionToken를 설정합니다. 속성을 사용하여 토큰을 사용할 수 있습니다.

// Create a session token.
const token = new AutocompleteSessionToken();

// Add the token to the request.
// @ts-ignore
request.sessionToken = token;

fetchFields()가 발생하면 세션이 종료됩니다. 알 수 있습니다. Place 인스턴스를 만든 후에는 세션을 전달할 필요가 없습니다. 자동으로 처리되므로 fetchFields()에 토큰을 추가합니다.

await place.fetchFields({
  fields: ["displayName", "formattedAddress"],
});
await place.fetchFields({
    fields: ['displayName'],
  });

AutocompleteSessionToken의 새 인스턴스를 만들어 다음 세션의 세션 토큰을 만듭니다.

세션 토큰 추천:

  • 모든 Place Autocomplete 호출에 세션 토큰을 사용합니다.
  • 세션마다 새 토큰을 생성합니다.
  • 새 세션마다 고유한 세션 토큰을 전달합니다. 둘 이상의 세션에 동일한 토큰 사용 각 요청에 대해 개별적으로 요금이 청구됩니다.

선택적으로 요청에서 자동 완성 세션 토큰을 생략할 수 있습니다. 세션 토큰이 생략된 경우 각 요청에 대해 별도로 청구되어 Autocomplete - Per Request SKU. 세션 토큰을 재사용하면 세션이 유효하지 않은 것으로 간주되어 요청에 요금이 청구됩니다. 세션 토큰이 제공되지 않은 것처럼 보입니다.

사용자가 검색어를 입력할 때 자동 완성 요청이 몇 시간마다 호출됩니다. 키 입력 (문자별이 아님)하고 가능한 결과 목록이 반환됩니다. 사용자가 결과 목록에서 항목을 선택하면 선택 항목이 검색 중에 이루어진 모든 요청은 번들로 묶여 단일 요청으로 간주됩니다. 사용자가 장소를 선택하면 검색어는 무료로 사용할 수 있으며 장소 데이터 요청에만 요금이 청구됩니다. 사용자가 선택할 수 없는 경우에는 비용이 청구되기 때문입니다

앱의 관점에서 볼 때 이벤트 흐름은 다음과 같습니다.

  1. 사용자가 '프랑스 파리'를 검색하기 위해 검색어를 입력하기 시작합니다.
  2. 사용자 입력을 감지하면 앱이 새 세션을 만듭니다. 토큰, '토큰 A'.
  3. 사용자가 입력할 때 API는 몇 시간마다 자동 완성을 요청합니다. 문자(
    )에 대한 잠재적인 결과의 새로운 목록이 표시됩니다. 'P'
    '파'
    '파리'
    "파리, Fr"
  4. 사용자가 선택하는 경우: <ph type="x-smartling-placeholder">
      </ph>
    • 쿼리에서 발생하는 모든 요청이 그룹화되어 세션을 단일 요청으로 표시합니다.
    • 사용자가 선택한 항목은 장소 세부정보 요청으로 집계되어 '토큰 A'로 표시된 세션으로 전달됩니다.
  5. 세션이 종료되고 앱에서 '토큰 A'를 삭제합니다.
를 통해 개인정보처리방침을 정의할 수 있습니다. 세션 요금 청구 방식 알아보기

예시 코드 작성

이 섹션에는 Place Autocomplete Data API 를 사용하는 방법을 보여주는 전체 예제가 포함되어 있습니다 .

장소 자동 완성 예상 검색어

다음 예는 fetchAutocompleteSuggestions() 드림 입력 'Tadi'를 찾은 후 toPlace()를 호출합니다. 첫 번째 예상 검색어 결과에서 실행된 다음 장소 세부정보를 가져오기 위한 fetchFields() 호출이 이어집니다.

TypeScript

/**
 * Demonstrates making a single request for Place predictions, then requests Place Details for the first result.
 */
async function init() {
    // @ts-ignore
    const { Place, AutocompleteSessionToken, AutocompleteSuggestion } = await google.maps.importLibrary("places") as google.maps.PlacesLibrary;

    // Add an initial request body.
    let request = {
        input: "Tadi",
        locationRestriction: { west: -122.44, north: 37.8, east: -122.39, south: 37.78 },
        origin: { lat: 37.7893, lng: -122.4039 },
        includedPrimaryTypes: ["restaurant"],
        language: "en-US",
        region: "us",
    };

    // Create a session token.
    const token = new AutocompleteSessionToken();
    // Add the token to the request.
    // @ts-ignore
    request.sessionToken = token;
    // Fetch autocomplete suggestions.
    const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);

    const title = document.getElementById('title') as HTMLElement;
    title.appendChild(document.createTextNode('Query predictions for "' + request.input + '":'));

    for (let suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;

        // Create a new list element.
        const listItem = document.createElement('li');
        const resultsElement = document.getElementById("results") as HTMLElement;
        listItem.appendChild(document.createTextNode(placePrediction.text.toString()));
        resultsElement.appendChild(listItem);
    }

    let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place.
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress'],
    });

    const placeInfo = document.getElementById("prediction") as HTMLElement;
    placeInfo.textContent = 'First predicted place: ' + place.displayName + ': ' + place.formattedAddress;

}

init();

JavaScript

/**
 * Demonstrates making a single request for Place predictions, then requests Place Details for the first result.
 */
async function init() {
  // @ts-ignore
  const { Place, AutocompleteSessionToken, AutocompleteSuggestion } =
    await google.maps.importLibrary("places");
  // Add an initial request body.
  let request = {
    input: "Tadi",
    locationRestriction: {
      west: -122.44,
      north: 37.8,
      east: -122.39,
      south: 37.78,
    },
    origin: { lat: 37.7893, lng: -122.4039 },
    includedPrimaryTypes: ["restaurant"],
    language: "en-US",
    region: "us",
  };
  // Create a session token.
  const token = new AutocompleteSessionToken();

  // Add the token to the request.
  // @ts-ignore
  request.sessionToken = token;

  // Fetch autocomplete suggestions.
  const { suggestions } =
    await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);
  const title = document.getElementById("title");

  title.appendChild(
    document.createTextNode('Query predictions for "' + request.input + '":'),
  );

  for (let suggestion of suggestions) {
    const placePrediction = suggestion.placePrediction;
    // Create a new list element.
    const listItem = document.createElement("li");
    const resultsElement = document.getElementById("results");

    listItem.appendChild(
      document.createTextNode(placePrediction.text.toString()),
    );
    resultsElement.appendChild(listItem);
  }

  let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place.

  await place.fetchFields({
    fields: ["displayName", "formattedAddress"],
  });

  const placeInfo = document.getElementById("prediction");

  placeInfo.textContent =
    "First predicted place: " +
    place.displayName +
    ": " +
    place.formattedAddress;
}

init();

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
#map {
  height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

HTML

<html>
  <head>
    <title>Place Autocomplete Data API Predictions</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="title"></div>
    <ul id="results"></ul>
    <p><span id="prediction"></span></p>
    <img
      class="powered-by-google"
      src="https://storage.googleapis.com/geo-devrel-public-buckets/powered_by_google_on_white.png"
      alt="Powered by Google"
    />

    <!-- prettier-ignore -->
    <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
        ({key: "AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg", v: "weekly"});</script>
  </body>
</html>

샘플 사용해 보기

세션으로 자동 완성 미리 입력 배치

이 예에서는 fetchAutocompleteSuggestions() 드림 응답으로 예상 장소 목록을 표시하고 장소 세부정보입니다. 이 예시에서는 세션 토큰을 사용하여 최종 장소 세부정보 요청으로 사용자 쿼리를 그룹화합니다.

TypeScript

let title;
let results;
let input;
let token;

// Add an initial request body.
let request = {
    input: "",
    locationRestriction: { west: -122.44, north: 37.8, east: -122.39, south: 37.78 },
    origin: { lat: 37.7893, lng: -122.4039 },
    includedPrimaryTypes: ["restaurant"],
    language: "en-US",
    region: "us",
};

async function init() {
    token = new google.maps.places.AutocompleteSessionToken();

    title = document.getElementById('title');
    results = document.getElementById('results');
    input = document.querySelector("input");
    input.addEventListener("input", makeAcRequest);
    request = refreshToken(request) as any;
}

async function makeAcRequest(input) {
    // Reset elements and exit if an empty string is received.
    if (input.target.value == '') {
        title.innerText = '';
        results.replaceChildren();
        return;
    }

    // Add the latest char sequence to the request.
    request.input = input.target.value;

    // Fetch autocomplete suggestions and show them in a list.
    // @ts-ignore
    const { suggestions } = await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(request);

    title.innerText = 'Query predictions for "' + request.input + '"';

    // Clear the list first.
    results.replaceChildren();

    for (const suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;

        // Create a link for the place, add an event handler to fetch the place.
        const a = document.createElement('a');
        a.addEventListener('click', () => {
            onPlaceSelected(placePrediction.toPlace());
        });
        a.innerText = placePrediction.text.toString();

        // Create a new list element.
        const li = document.createElement('li');
        li.appendChild(a);
        results.appendChild(li);
    }
}

// Event handler for clicking on a suggested place.
async function onPlaceSelected(place) {
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress'],
    });
    let placeText = document.createTextNode(place.displayName + ': ' + place.formattedAddress);
    results.replaceChildren(placeText);
    title.innerText = 'Selected Place:';
    input.value = '';
    refreshToken(request);
}

// Helper function to refresh the session token.
async function refreshToken(request) {
    // Create a new session token and add it to the request.
    token = new google.maps.places.AutocompleteSessionToken();
    request.sessionToken = token;
    return request;
}

declare global {
    interface Window {
      init: () => void;
    }
  }
  window.init = init;

JavaScript

let title;
let results;
let input;
let token;
// Add an initial request body.
let request = {
  input: "",
  locationRestriction: {
    west: -122.44,
    north: 37.8,
    east: -122.39,
    south: 37.78,
  },
  origin: { lat: 37.7893, lng: -122.4039 },
  includedPrimaryTypes: ["restaurant"],
  language: "en-US",
  region: "us",
};

async function init() {
  token = new google.maps.places.AutocompleteSessionToken();
  title = document.getElementById("title");
  results = document.getElementById("results");
  input = document.querySelector("input");
  input.addEventListener("input", makeAcRequest);
  request = refreshToken(request);
}

async function makeAcRequest(input) {
  // Reset elements and exit if an empty string is received.
  if (input.target.value == "") {
    title.innerText = "";
    results.replaceChildren();
    return;
  }

  // Add the latest char sequence to the request.
  request.input = input.target.value;

  // Fetch autocomplete suggestions and show them in a list.
  // @ts-ignore
  const { suggestions } =
    await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(
      request,
    );

  title.innerText = 'Query predictions for "' + request.input + '"';
  // Clear the list first.
  results.replaceChildren();

  for (const suggestion of suggestions) {
    const placePrediction = suggestion.placePrediction;
    // Create a link for the place, add an event handler to fetch the place.
    const a = document.createElement("a");

    a.addEventListener("click", () => {
      onPlaceSelected(placePrediction.toPlace());
    });
    a.innerText = placePrediction.text.toString();

    // Create a new list element.
    const li = document.createElement("li");

    li.appendChild(a);
    results.appendChild(li);
  }
}

// Event handler for clicking on a suggested place.
async function onPlaceSelected(place) {
  await place.fetchFields({
    fields: ["displayName", "formattedAddress"],
  });

  let placeText = document.createTextNode(
    place.displayName + ": " + place.formattedAddress,
  );

  results.replaceChildren(placeText);
  title.innerText = "Selected Place:";
  input.value = "";
  refreshToken(request);
}

// Helper function to refresh the session token.
async function refreshToken(request) {
  // Create a new session token and add it to the request.
  token = new google.maps.places.AutocompleteSessionToken();
  request.sessionToken = token;
  return request;
}

window.init = init;

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
#map {
  height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

a {
  cursor: pointer;
  text-decoration: underline;
  color: blue;
}

input {
  width: 300px;
}

HTML

<html>
  <head>
    <title>Place Autocomplete Data API Session</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <input id="input" type="text" placeholder="Search for a place..." />
    <div id="title"></div>
    <ul id="results"></ul>
    <img
      class="powered-by-google"
      src="https://storage.googleapis.com/geo-devrel-public-buckets/powered_by_google_on_white.png"
      alt="Powered by Google"
    />

    <!-- 
      The `defer` attribute causes the script to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises. See
      https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=init&libraries=places&v=weekly"
      defer
    ></script>
  </body>
</html>

샘플 사용해 보기