Google Maps API 웹 서비스

Google Maps 웹 서비스는 지도 애플리케이션에 지리 데이터를 제공하는 Google 서비스의 HTTP 인터페이스 컬렉션입니다. 이 가이드에서는 모든 다른 서비스에 공통되는 웹 서비스 및 호스트 정보에 대해서만 소개합니다. 각 서비스의 개별 문서는 아래에 나와 있습니다.

내게 필요한 API 찾기

API 선택기를 사용하여 자신의 프로젝트에 맞는 API를 찾아보세요.

웹 서비스에 대한 추가 정보

이 가이드의 나머지 부분에서는 웹 서비스 요청을 설정하고 응답을 구문 분석하는 기술에 대해 논의합니다. 그러나 각 서비스의 특정 문서에 대해서는 적절한 문서를 참조해야 합니다.

웹 서비스란 무엇인가요?

Google Maps API는 외부 서비스에서 Maps API 데이터를 요청하고 이 데이터를 지도 애플리케이션 내에서 사용하기 위한 인터페이스로서 이들 웹 서비스를 제공합니다. 이들 웹 서비스는 Maps API 서비스 약관 라이선스 제한에 따라, 지도와 함께 사용하도록 설계되었습니다.

이들 웹 서비스는 특정 URL에 대한 HTTP 요청을 사용하며, URL 매개변수를 인수로 해당 서비스에 전달합니다. 일반적으로 이들 서비스는 HTTP 요청에서 JSON 또는 XML 중 하나로 데이터를 반환하며, 이 데이터를 애플리케이션이 구문 분석하고 처리합니다.

일반적인 웹 서비스 요청의 형식은 다음과 같습니다.

https://maps.googleapis.com/maps/api/service/output?parameters

여기서 service는 요청된 특정 서비스를 나타내며 output은 응답 형식을 나타냅니다(일반적으로 json 또는 xml).

각 서비스의 전체 문서는 이들 서비스의 특정 개발자 가이드 내에 포함되어 있습니다. 그러나, 이 가이드에서는 웹 서비스 요청을 설정하고 웹 서비스 응답을 처리하는 데 유용한 몇 가지 공통적인 방법만 다룹니다.

SSL 액세스

https://maps.googleapis.com/maps/api/service/output?parameters

HTTPS는 사용자 데이터 또는 개발자 ID를 포함하는 모든 Maps API 웹 서비스 요청에 필요합니다. 중요한 데이터가 포함된 HTTP를 통한 요청은 거부될 수 있습니다.

올바른 URL 빌드

"올바른" URL이 자명하다고 생각할 수 있지만, 사실은 그렇지가 않습니다. 예를 들어, 브라우저의 주소 표시줄에 입력된 URL에는 특수 문자가 포함될 수도 있습니다(예: "上海+中國"). 브라우저는 전송 전에 이러한 문자를 다른 인코딩으로 내부에서 변환해야 합니다. UTF-8 입력을 생성하거나 허용하는 모든 코드는 동일한 토큰으로 UTF-8 문자를 "올바른" 문자로 처리할 수도 있지만, 또한 이러한 문자를 웹 서버로 전송하기 전에 변환해야 합니다. 이 프로세스를 URL 인코딩이라고 합니다.

특수 문자를 변환해야 하는 이유는 모든 URL은 W3 URI(Uniform Resource Identifier) 사양에 의해 지정된 구문을 준수해야 하기 때문입니다. 즉, 실제로는 ASCII 문자의 특수한 하위 집합(예: 친숙한 영숫자 기호와 URL 내에 제어 문자로 사용되는 일부 예약 문자)만이 URL에 포함되어야 합니다. 아래 표에 이러한 문자들이 요약되어 있습니다.

올바른 URL 문자 요약
집합문자URL 사용
영숫자 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 텍스트 문자열, 구성표 사용(http), 포트(8080) 등
예약되지 않음 - _ . ~ 텍스트 문자열
예약됨 ! * ' ( ) ; : @ & = + $ , / ? % # [ ] 제어 문자 및/또는 텍스트 문자열

올바른 URL을 빌드할 경우, 위에 나타난 문자만을 포함하도록 해야 합니다. URL이 이러한 문자 집합 사용을 준수하다보면, 일반적으로 다음과 같은 누락 및 대체의 두 가지 사안이 발생합니다.

  • 처리하려는 문자가 위의 집합 안에 없습니다. 예를 들어, 上海+中國과 같은 외국 언어의 문자는 위의 문자를 사용하여 인코딩되어야 합니다. 널리 사용되는 관행으로, (URL 내에 허용되지 않는) 공백은 대개 '+' 문자를 사용하여 표현되기도 합니다.
  • 문자가 예약 문자로 위의 집합 내에 있더라도, 정확하게 사용되어야 합니다. 예를 들어, ?는 URL 내에서 쿼리 문자열의 시작을 나타내는 데 사용되며, 문자열 "? and the Mysterians"를 사용하려면, '?' 문자를 인코딩해야 합니다.

URL 인코딩되는 모든 문자는 '%' 문자와 UTF-8 문자에 해당하는 두 자리 16진수 값을 사용하여 인코딩됩니다. 예를 들어, UTF-8 형식의 上海+中國%E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B로 URL 인코딩됩니다. 문자열 ? and the Mysterians%3F+and+the+Mysterians로 URL 인코딩됩니다.

일부 공통 문자는 다음과 같이 인코딩되어야 합니다.

안전하지 않은 문자 인코딩된 값
공백 %20
" %22
< %3C
> %3E
# %23
% %25
| %7C

때로는 사용자가 입력한 URL을 수신하여 변환하는 과정이 까다로울 수 있습니다. 예를 들어, 사용자가 주소를 "5th&Main St."로 입력할 수 있습니다. 일반적으로, 이러한 부분으로부터 URL을 구성해야 하며, 모든 사용자 입력을 문자 그대로 취급해야 합니다.

또한 URL은 모든 웹 서비스에서 2048자로 제한됩니다. 대부분의 서비스에서는 이러한 문자 제한에 거의 도달하지 않습니다. 그러나, 일부 서비스에는 URL을 길게 만들 수 있는 여러 매개변수가 있습니다.

적절한 Google API 사용

잘못 설계된 API 클라이언트는 인터넷과 Google 서버에서 필요한 것보다 많은 부하를 유발할 수 있습니다. 이 섹션에는 API 클라이언트의 모범 사례가 포함되어 있습니다. 모범 사례를 따르면 API를 부주의하게 사용하여 애플리케이션이 차단되는 것을 방지할 수 있습니다.

지수 백오프

요청을 처리할 때 드물게 문제가 발생할 수 있습니다. 가령, 4XX 또는 5XX HTTP 응답 코드를 받거나 클라이언트와 Google 서버 간 TCP 연결이 실패할 수 있습니다. 원래 요청이 실패한 뒤 후속 요청이 성공할 수 있으므로 요청을 다시 시도하는 것이 좋습니다. 그러나 요청을 Google 서버에 반복적으로 보내지 않는 것이 좋습니다. 이 반복 동작으로 클라이언트와 Google 간 네트워크에 과부하가 발생하여 많은 문제에 직면할 수 있습니다.

따라서 시도 사이의 지연 시간을 늘려 재시도하는 것이 훨씬 좋습니다. 일반적으로 지연 시간은 각 시도의 승수만큼 증가합니다. 이런 접근 방식을 지수 백오프라고 합니다.

예를 들어, Google Maps Time Zone API에 이런 요청을 하려는 애플리케이션을 생각해 봅시다.

https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510&timestamp=1331161200&key=YOUR_API_KEY

다음 Python 예시는 지수 백오프 요청 방법을 보여줍니다.

import json
import time
import urllib
import urllib2

def timezone(lat, lng, timestamp):
    # The maps_key defined below isn't a valid Google Maps API key.
    # You need to get your own API key.
    # See https://developers.google.com/maps/documentation/timezone/get-api-key
    maps_key = 'YOUR_KEY_HERE'
    timezone_base_url = 'https://maps.googleapis.com/maps/api/timezone/json'

    # This joins the parts of the URL together into one string.
    url = timezone_base_url + '?' + urllib.urlencode({
        'location': "%s,%s" % (lat, lng),
        'timestamp': timestamp,
        'key': maps_key,
    })

    current_delay = 0.1  # Set the initial retry delay to 100ms.
    max_delay = 3600  # Set the maximum retry delay to 1 hour.

    while True:
        try:
            # Get the API response.
            response = str(urllib2.urlopen(url).read())
        except IOError:
            pass  # Fall through to the retry loop.
        else:
            # If we didn't get an IOError then parse the result.
            result = json.loads(response.replace('\\n', ''))
            if result['status'] == 'OK':
                return result['timeZoneId']
            elif result['status'] != 'UNKNOWN_ERROR':
                # Many API errors cannot be fixed by a retry, e.g. INVALID_REQUEST or
                # ZERO_RESULTS. There is no point retrying these requests.
                raise Exception(result['error_message'])

        if current_delay > max_delay:
            raise Exception('Too many retry attempts.')
        print 'Waiting', current_delay, 'seconds before retrying.'
        time.sleep(current_delay)
        current_delay *= 2  # Increase the delay each time we retry.

tz = timezone(39.6034810, -119.6822510, 1331161200)
print 'Timezone:', tz

또한 반복적인 요청을 연속적으로 발생하게 하는 애플리케이션 호출 체인의 높은 재시도 코드가 없도록 주의해야 합니다.

동기화된 요청

Google의 API에 대한 수많은 동기화된 요청은 Google 인프라에서 분산 서비스 거부(DDoS) 공격처럼 보이고 그에 따라 처리될 수 있습니다. 이를 피하려면 API 요청이 클라이언트 간에 동기화되지 않아야 합니다.

예를 들어, 현재 시간대의 시간을 표시하는 애플리케이션을 생각해 봅시다. 이 애플리케이션은 표시된 시간을 업데이트할 수 있도록 클라이언트 운영 체제에 분(minute) 시작 시점에 절전 모드를 해제하는 알람을 설정합니다. 애플리케이션은 해당 알람과 관련된 처리의 일환으로 API를 호출해서는 안 됩니다.

고정 알람에 대한 응답으로 API를 호출하는 것은 API 호출을 시간이 지나면서 균등하게 분산하는 것이 아니라, 서로 다른 기기 사이에서도 분 시작 시점에 동기화시키므로 바람직하지 않습니다. 잘못 설계된 애플리케이션은 각 분 시작 시점에서 정상 수준의 60배에 달하는 트래픽을 발생시킵니다.

이 문제를 해결하려면 두 번째 알람을 임의로 선택한 시간으로 설정하도록 설계하면 됩니다. 이 두 번째 알람이 발생하면 애플리케이션은 필요한 모든 API를 호출하고 결과를 저장합니다. 애플리케이션은 API를 다시 호출하지 않고 이전에 저장한 결과를 사용하여 분 시작 시점에서 디스플레이를 업데이트합니다. 이 방법을 사용하면 API 호출이 시간이 지남에 따라 고르게 분산됩니다. 또한 API 호출은 디스플레이를 업데이트할 때 렌더링을 지연시키지 않습니다.

분 시작 시점 외에 시간(hour) 시작 시점과 일(day) 시작 시점도 일반 동기화 시간의 대상으로 지정하지 않도록 주의해야 합니다.

응답 처리

웹 서비스 요청에 대한 개별 응답은 그 형식의 정확성이 보장되지 않으므로(일부 요소가 누락되거나 여러 위치에 있을 수 있음), 지정된 응답에 대해 반환되는 형식이 다른 쿼리에 대해서도 동일한 것으로 가정해서는 절대 안됩니다. 그 대신, 을 통해 응답을 처리하고 적절한 값을 선택해야 합니다. 이 섹션에서는 웹 서비스 응답에서 이들 값을 동적으로 추출하는 방법에 대해 설명합니다.

Google Maps 웹 서비스는 이해하기 쉬운 응답을 제공하지만, 이 응답이 항상 사용자에게 친숙한 것은 아닙니다. 데이터 집합을 표시할 때가 아니라 쿼리를 수행할 때 여러분은 아마 몇 가지 특정 값을 추출하기를 원할 것입니다. 일반적으로 웹 서비스에서 응답을 구문 분석하고, 관심이 있는 값만 추출하기를 원할 것입니다.

여러분이 사용하는 구문 분석 구성표는 출력을 XML 또는 JSON으로 반환하는지에 따라 다릅니다. JSON 응답은 이미 JavaScript 객체의 형식으로 되어 있으므로 클라이언트상의 JavaScript 내에서 처리될 수 있지만, XML 응답은 XML 형식 내의 요소를 다루기 위해 XML 프로세서 및 XML 쿼리 언어를 사용하여 처리되어야 합니다. 다음 예시에서 우리는 XML 처리 라이브러리에서 공통적으로 지원되는 XPath를 사용합니다.

XPath로 XML 처리

XML은 데이터 교환에 사용되는 비교적 성숙한 구조적 정보 형식입니다. XML은 JSON만큼 가볍지는 않지만, 더 많은 언어를 지원하는 보다 강력한 도구입니다. 예를 들어, Java에서 XML을 처리하기 위한 코드는 javax.xml 패키지에 빌드됩니다.

XML 응답을 처리할 경우, XML 문서 내의 노드를 선택할 때 적절한 퀴리 언어를 사용해야 하며, XML 마크업 내의 절대 위치에 요소가 있을 것이라고 가정해서는 안됩니다. XPath는 XML 문서 내의 노드와 요소를 고유하게 표현하기 위한 언어 구문입니다. XPath 식을 사용하면 XML 응답 문서 내의 특정 콘텐츠를 식별할 수 있습니다.

XPath 식

XPath에 친숙해진다면 강력한 구문 분석 구성표를 개발하는 데 큰 도움이 됩니다. 이 섹션에서는 여러 요소를 다루고 복잡한 쿼리를 구성할 수 있도록, XPath를 사용하여 XML 문서 내의 요소를 다루는 방법에 대해 주로 설명합니다.

XPath에서는 을 사용하여 XML 문서 내의 요소를 선택하며, 디렉토리 경로에 사용되는 것과 유사한 구문을 사용합니다. 이 식은 XML 문서 트리 내의 요소를 식별하며, 이 트리는 DOM의 계층적 트리와 유사합니다. 일반적으로, XPath 식은 입력된 기준과 일치하는 모든 노드를 비교합니다.

우리는 예를 보여주기 위해 다음과 같은 추상 XML을 사용합니다.

<WebServiceResponse>
 <status>OK</status>
 <result>
  <type>sample</type>
  <name>Sample XML</name>
  <location>
   <lat>37.4217550</lat>
   <lng>-122.0846330</lng>
  </location>
 </result>
 <result>
  <message>The secret message</message>
 </result>
</WebServiceResponse>

식에서 노드 선택

XPath 선택에서는 노드를 선택합니다. 루트 노드는 전체 문서를 포함합니다. 특수 식 "/"를 사용하여 이 노드를 선택합니다. 참고로, 루트 노드는 XML 문서의 최상위 노드가 아니며, 실제로는 이 최상위 요소보다 한 수준 위에 있고 최상위 요소를 포함합니다.

요소 노드는 XML 문서 트리 내의 다양한 요소를 나타냅니다. 예를 들어, <WebServiceResponse> 요소는 위의 샘플 서비스에서 반환되는 최상위 요소를 나타냅니다. 선행 "/" 문자의 존재 여부에 따라 표시되는 절대 또는 상대 경로를 통해 개별 노드를 선택할 수 있습니다.

  • 절대 경로: "/WebServiceResponse/result" 식은 <WebServiceResponse> 노드의 하위 노드인 모든 <result> 노드를 선택합니다. (참고로, 이들 두 요소는 루트 노드인 "/"에서 상속됩니다.)
  • 현재 컨텍스트의 상대 경로: "result" 식은 현재 컨텍스트 내의 모든 <result> 요소를 비교합니다. 일반적으로, 웹 서비스 결과는 단일 식을 통해 처리되기 때문에 컨텍스트에 대해서는 걱정하지 않아도 됩니다.

이중 슬래시("//")로 표시되는 와일드카드 경로를 추가하여 이들 식을 보강할 수 있습니다. 이 와일드카드는 중간 경로에서 0개 이상의 요소가 일치할 수 있음을 나타냅니다. 예를 들어, XPath 식 "//formatted_address"는 현재 문서에서 해당 이름을 가진 모든 노드를 비교합니다. //viewport//lat 식은 <viewport>를 상위 요소로 하여 추적할 수 있는 모든 <lat> 요소를 비교합니다.

기본적으로 XPath 식은 모든 요소를 비교합니다. 대괄호([])로 둘러싸인 조건자를 제공하여, 특정 요소만을 비교하도록 식을 제한할 수 있습니다. XPath 식 "/GeocodeResponse/result[2]는 항상 두 번째 결과를 반환합니다. 예:

식의 유형
루트 노드
XPath 식:  "/"
선택:
    <WebServiceResponse>
     <status>OK</status>
     <result>
      <type>sample</type>
      <name>Sample XML</name>
      <location>
       <lat>37.4217550</lat>
       <lng>-122.0846330</lng>
      </location>
     </result>
     <result>
      <message>The secret message</message>
     </result>
    </WebServiceResponse>
    
절대 경로
XPath 식:  "/WebServiceResponse/result"
선택:
    <result>
     <type>sample</type>
     <name>Sample XML</name>
     <location>
      <lat>37.4217550</lat>
      <lng>-122.0846330</lng>
     </location>
    </result>
    <result>
     <message>The secret message</message>
    </result>
    
와일드카드가 있는 경로
XPath 식:  "/WebServiceResponse//location"
선택:
    <location>
     <lat>37.4217550</lat>
     <lng>-122.0846330</lng>
    </location>
    
조건자가 있는 경로
XPath 식:  "/WebServiceResponse/result[2]/message"
선택:
    <message>The secret message</message>
    
첫 번째 result의 모든 직계 자식
XPath 식:  "/WebServiceResponse/result[1]/*"
선택:
     <type>sample</type>
     <name>Sample XML</name>
     <location>
      <lat>37.4217550</lat>
      <lng>-122.0846330</lng>
     </location>
    
type 텍스트가 "sample"인 resultname.
XPath 식:  "/WebServiceResponse/result[type/text()='sample']/name"
선택:
    Sample XML
    

요소를 선택할 때 중요한 점은, 단순히 객체 내의 텍스트를 선택하는 것이 아니라 노드를 선택하는 것입니다. 일반적으로 일치하는 모든 노드에 대해 반복 수행하고 텍스트를 추출하기를 원할 것입니다. 또한, 텍스트 노드를 직접 비교할 수도 있습니다. 아래의 텍스트 노드 를 참조하세요.

참고로, XPath는 특성 노드도 지원합니다. 그러나, 모든 Google Maps 웹 서비스는 특성이 없는 요소를 지원하므로, 특성 비교는 불필요합니다.

식에서 텍스트 선택

XML 문서 내의 텍스트는 텍스트 노드 연산자를 통해 XPath 식에 지정됩니다. 이 연산자 "text()"는 표시된 노드에서 텍스트가 추출됨을 나타냅니다. 예를 들어, XPath 식 "//formatted_address/text()"는 <formatted_address> 요소 내의 모든 텍스트를 반환합니다.

식의 유형
모든 텍스트 노드(공백 포함)
XPath 식:  "//text()"
선택:
    sample
    Sample XML

    37.4217550
    -122.0846330
    The secret message
    
텍스트 선택
XPath 식:  "/WebServiceRequest/result[2]/message/text()"
선택:
    The secret message
    
컨텍스트에 따른 선택
XPath 식:  "/WebServiceRequest/result[type/text() = 'sample']/name/text()"
선택:
    Sample XML
    

다른 방법으로, 식을 평가하고 노드 집합을 반환한 다음, 이 "노드 집합"에 대해 반복 수행하여 각 노드에서 텍스트를 추출할 수도 있습니다. 아래 예시에서는 이 방법을 사용합니다.

XPath에 대한 자세한 내용은, XPath W3C 사양을 참조하세요.

Java에서 XPath 평가

Java는 javax.xml.xpath.* 패키지 내에서 XML을 구문 분석하고 XPath 식을 사용할 수 있는 다양한 기능을 지원합니다. 이러한 이유로, 이 섹션의 샘플 코드에서는 XML을 다루고 XML 서비스 응답에서 데이터를 구문 분석하는 방법을 보여주기 위해 Java를 사용합니다.

Java 코드에서 XPath를 사용하려면, 먼저 XPathFactory의 인스턴스를 생성하고 해당 팩터리에서 newXPath()를 호출하여 XPath 객체를 생성해야 합니다. 그러면 이 객체가 evaluate() 메서드를 사용하여 전달된 XML 및 XPath 식을 처리할 수 있습니다.

XPath 식을 평가할 때, 반환될 수 있는 가능한 모든 "노드 집합"에 대해 반복 수행하도록 하십시오. 이 결과는 DOM 노드로 Java 코드에 반환되기 때문에, NodeList 객체 내의 이러한 복수의 값을 캡처하고 해당 객체에 대해 반복 수행하여 이들 노드로부터 텍스트 또는 값을 추출해야 합니다.

다음 코드는 XPath 객체를 생성하여 XML 및 XPath 식에 할당하고, 식을 평가하여 관련 콘텐츠를 출력하는 방법을 보여줍니다.

import org.xml.sax.InputSource;
import org.w3c.dom.*;
import javax.xml.xpath.*;
import java.io.*;

public class SimpleParser {

  public static void main(String[] args) throws IOException {

	XPathFactory factory = XPathFactory.newInstance();

    XPath xpath = factory.newXPath();

    try {
      System.out.print("Web Service Parser 1.0\n");

      // In practice, you'd retrieve your XML via an HTTP request.
      // Here we simply access an existing file.
      File xmlFile = new File("XML_FILE");

      // The xpath evaluator requires the XML be in the format of an InputSource
	  InputSource inputXml = new InputSource(new FileInputStream(xmlFile));

      // Because the evaluator may return multiple entries, we specify that the expression
      // return a NODESET and place the result in a NodeList.
      NodeList nodes = (NodeList) xpath.evaluate("XPATH_EXPRESSION", inputXml, XPathConstants.NODESET);

      // We can then iterate over the NodeList and extract the content via getTextContent().
      // NOTE: this will only return text for element nodes at the returned context.
      for (int i = 0, n = nodes.getLength(); i < n; i++) {
        String nodeString = nodes.item(i).getTextContent();
        System.out.print(nodeString);
        System.out.print("\n");
      }
    } catch (XPathExpressionException ex) {
	  System.out.print("XPath Error");
    } catch (FileNotFoundException ex) {
      System.out.print("File Error");
    }
  }
}

js-v2-samples에서 코드를 다운로드하세요.

Javascript로 JSON 처리

JSON(Javascript Object Notation)은 XML에 비해 응답이 가볍다는 큰 이점이 있습니다. JSON은 이미 그 형식이 올바른 JavaScript 객체이기 때문에 JavaScript에서 이러한 결과를 구문 분석하는 것은 쉬운 일입니다. 예를 들어, JSON 결과 객체 내에서 'formatted_address' 키의 값을 추출하려면, 다음과 같은 코드를 사용하여 액세스하면 됩니다.

for (i = 0; i < myJSONResult.results.length; i++) {
  myAddress[i] = myJSONResult.results[i].formatted_address;
}

참고로, JSON에는 복수의 값이 포함될 수 있으므로, 모든 가능한 값을 캡처하려면 results 배열 범위에 대해 반복 수행하는 것이 최선의 방법입니다. 그러나 실제로는, 첫 번째 결과(results[0])만을 반환하는 것이 좋을 수 있습니다.

다른 언어로 JSON을 구문 분석하는 것은 약간 더 어려울 수 있습니다. 다음의 Python 예에서는 지오코딩 웹 서비스 요청을 시작하고 모든 결과 formatted_address 값을 배열 내의 사용자에게 표시합니다.

import simplejson, urllib

GEOCODE_BASE_URL = 'https://maps.googleapis.com/maps/api/geocode/json'

def geocode(address, **geo_args):
    geo_args.update({
        'address': address
    })

    url = GEOCODE_BASE_URL + '?' + urllib.urlencode(geo_args)
    result = simplejson.load(urllib.urlopen(url))

    print simplejson.dumps([s['formatted_address'] for s in result['results']], indent=2)

if __name__ == '__main__':
    geocode(address="San+Francisco")

Output: [ "San Francisco, CA, USA" ]

js-v2-samples에서 코드를 다운로드하세요.

sensor 매개변수

이전의 Google Maps API는 애플리케이션이 사용자의 위치 파악을 위해 센서를 사용했는지 여부를 나타내기 위해 sensor 매개변수를 포함하도록 요구했습니다. 이 매개변수는 더 이상 필요하지 않습니다.

다음에 대한 의견 보내기...

Google Maps Web Service API
Google Maps Web Service API