카카오 맵 API를 활용한 좌표 <-> 주소 변환

API 활용 준비

https://developers.kakao.com

카카오 개발자 페이지에서 여러 카카오 제품의 API를 활용할 수 있는데, 그 중에서 좌표와 주소 변환 관련해서는 지도/로컬 제품을 사용하면 됩니다.

REST API 테스트 페이지에서는 어떤 기능을 어떻게 활용할 수 있는지 확인할 수 있습니다. 확인해 볼 기능은 좌표와 주소간 변환이니 아래 이미지의 노란색 2개를 확인해보겠습니다.

좌표변환

주소 -> 좌표 변환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import requests

KAKAO_REST_API_KEY = '' # 발급받은 API KEY

def convert_address_to_coordinates(address):
"""
입력받은 주소를 WGS84 좌표계 좌표로 변환
"""

url = 'https://dapi.kakao.com/v2/local/search/address.json?query=' + address
header = {'Authorization': 'KakaoAK ' + KAKAO_REST_API_KEY}

r = requests.get(url, headers=header)

if r.status_code == 200:
lng = float(r.json()["documents"][0]["address"]['x'])
lat = float(r.json()["documents"][0]["address"]['y'])
else:
return None

return lat, lng

# Test
convert_address_to_coordinates("서울특별시 강남구 강남대로 396") # 강남역 주소

# Output
# (37.4981646510326, 127.028307900881)

좌표가 맞는지 지도에 찍어봤는데, 강남역을 가리키고 있습니다.

지도좌표검색

좌표 -> 주소 변환

이번에는 좌표에서 주소로 변환해보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def convert_coordinates_to_address(lat, lng):
"""
입력받은 위도, 경도를 도로명, 지번 주소로 변환
"""

y, x = str(lat), str(lng)
url = 'https://dapi.kakao.com/v2/local/geo/coord2address.json?x={}&y={}'.format(x, y)
header = {'Authorization': 'KakaoAK ' + KAKAO_REST_API_KEY}

r = requests.get(url, headers=header)

if r.status_code == 200:
road_address = r.json()["documents"][0]["road_address"]['address_name']
bunji_address = r.json()["documents"][0]["address"]['address_name']
else:
return None

return road_address, bunji_address

# TEST
convert_coordinates_to_address(37.4981646510326, 127.028307900881)

# Output
# ('서울특별시 강남구 강남대로 396', '서울 강남구 역삼동 804')

이전에 강남역 좌표로 얻은 것을 다시 역지오코딩을 했을 때 강남역 주소가 나오는 것을 확인할 수 있습니다.

Open Source Routing Machine (OSRM) with Python

OSRM 최적의 경로 찾기

Open Source Routing Machine (OSRM)은 지도상의 도로 Network에서 최단 경로를 계산하는 C ++ 라우팅 엔진입니다.

지도상의 포인트 A와 포인트 B 사이의 거리를 구하는 가장 쉬운 방법은 직선거리를 계산하는 것입니다.

그러나 직선거리로 계산하게되면 도로 상황을 무시해서 실제 이동거리와 많은 차이가 발생할 수 있는데, 이 OSRM API를 활용하면 네이버 길찾기처럼 경로, 소요시간, 이동거리 등과 같은 값을 얻을 수 있어서 유용합니다.

OSRM

API Document

API Document를 보면 Nearest, Route, Trip등 다양한 Service가 있는데, 이 중에서 Route service를 활용해보려고 합니다.

OSRM API Doc

신도림역 -> 문래역 Route

  • 이동수단도 선택이 가능한데 아래에서는 bike로 설정
    • car, bike, foot
  • route는 map에서 그리기 용이한 형태로 저장
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import requests
import folium
import polyline
import json
import pandas as pd

def get_route(origin_lon, origin_lat, dest_lon, dest_lat):
"""출발지, 도착지 좌표를 입력해서 Route 정보 Return"""

loc = "{},{};{},{}".format(origin_lon, origin_lat, dest_lon, dest_lat)
url = "http://router.project-osrm.org/route/v1/bike/"
r = requests.get(url + loc)
if r.status_code!= 200:
return {}

res = r.json()
routes = polyline.decode(res['routes'][0]['geometry'])
start_point = [res['waypoints'][0]['location'][1], res['waypoints'][0]['location'][0]]
end_point = [res['waypoints'][1]['location'][1], res['waypoints'][1]['location'][0]]
distance = res['routes'][0]['distance']

route = {'route':routes,
'start_point':start_point,
'end_point':end_point,
'distance':distance
}

return route


origin_lon, origin_lat, dest_lon, dest_lat = 126.890975,37.508767,126.89472929779438, 37.51792066883597
test_route = get_route(pickup_lon, pickup_lat, dropoff_lon, dropoff_lat)
1
2
3
4
5
6
7
8
9
10
11
12
13
{'route': [(37.50901, 126.89072),
(37.50918, 126.89083),
(37.50932, 126.89135),
(37.50992, 126.89262),
(37.51094, 126.89181),
(37.51198, 126.89393),
(37.51315, 126.89728),
(37.51476, 126.89392),
(37.51491, 126.89407),
(37.51792, 126.89477)],
'start_point': [37.50901, 126.890723],
'end_point': [37.517916, 126.894771],
'distance': 1584.2}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def get_map(route):
"""출발지, 도착지, route 정보를 folium map에 표시"""
route_map = folium.Map(location=[(route['start_point'][0] + route['end_point'][0])/2,
(route['start_point'][1] + route['end_point'][1])/2],
zoom_start=13)

folium.PolyLine(
route['route'],
weight=8,
color='blue',
opacity=0.6
).add_to(route_map)

folium.Marker(
location=route['start_point'],
icon=folium.Icon(icon='play', color='green')
).add_to(route_map)

folium.Marker(
location=route['end_point'],
icon=folium.Icon(icon='stop', color='red')
).add_to(route_map)

return route_map

Route 시각화

신도림역 -> 문래역 Route가 map에 잘 표현된 걸 확인할 수 있습니다.

OSRM API TEST