해당 게시글에서는 지도 화면이 아닌 JSON 데이터를 받는 방법입니다!
Flutter 에서 지도를 가져와 쓰고 싶을 때 물론 flutter 개발사인 구글 지도도 좋지만, 친근한 네이버 지도 , 카카오 지도 가 더 좋지 않을까? 해서 사용해보려고 한다.
카카오 지도 API 문서 와 네이버 지도 API 문서를 뒤적거리다. 내가 해보고 싶은건 지도도 지도지만 검색해서 나오는 마커 표시들이다.
찾아보니 네이버 지도 API 압도적으로 많다. ( 그 이유는 하다보니 알게 되었다. ) 일단 네이버가 설명이 개인적으로 잘 되어 있는 편이다. 근데 둘다 설명은 개인적으로 2% 부족한 편
( 내가 못찾은건가 싶기도 하다 )
일단 우리는 위 화면과 같은 목표로 개발하기 위해서 첫번 째로
네이버가 아닌 카카오 지도 API 중 하나인 Rest API ( 키워드로 검색하기 ) 를 사용해보려고 한다.
( 찾아보니 네이버 지도에는 키워드 검색하기가 20년도쯤에 종료된 것으로 안다. )
오늘은 요청하고 데이터를 받기만 하기 때문에 UI적 요소는 크게 필요 없다.
https://developers.kakao.com/
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
위 사이트에서 다음과 같이 진행하면 된다.
내 애플리케이션 클릭
추가하기 클릭
다음과 같이 기재
Flutter의 경우 앱 이름은 보통 com.example.${해당 프로젝트 이름으로 구성된다} 위치는 프로젝트 안에 android/app/build.gradle 에 해당 형식으로 적혀져 있다.
보통 manifest에 package명으로 기재되어 있음.
우리는 Rest API 이기 때문에 해당하는 부분을 사용하면 된다.
(아직은 플랫폼을 등록 안해도 된다.)
https://developers.kakao.com/docs/latest/ko/local/dev-guide
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
이제 Rest API 문서를 확인해 보자
우리는 이 중에서 키워드로 장소 검색하기 를 사용할 것이다!
요청시 Authorization 헤더와 쿼리 파라미터 query 는 필수 인 것을 알 수 있다.
curl -v -G GET "https://dapi.kakao.com/v2/local/search/keyword.json?y=37.514322572335935&x=127.06283102249932&radius=20000" -H "Authorization: KakaoAK ${REST_API_KEY}" --data-urlencode "query=카카오 프렌즈"
예시 코드를 cmd에서 시험해 보면 다음과 같은 결과를 알 수 있다.
그렇다면 우리는 이 결과를 통해 document가 List형식을 띄는 것을 알 수 있고 형식은 다음과 같다
그렇다면 우리의 위치를 기점으로 20km의 "카카오 프렌즈" 를 검색하고자 한다.
1-1. 우리의 위치를 찾기 위해 geolocator를 추가해 준다.
1-2. 안드로이드 manifest.xml에 위치(geolactor)와 인터넷(http 통신)을 추가해준다.
< uses-permission android:name = "android.permission.ACCESS_FINE_LOCATION" />
< uses-permission android:name = "android.permission.INTERNET" />
1-3. 다음과 같은 코드로 사용할 수 있다.
// 현재의 위도 경도 위치를 가져옴
Position position = await Geolocator . getCurrentPosition (
desiredAccuracy : LocationAccuracy . high );
position . latitude ; // 위도 y
position . longitude ; // 경도 x
2-1. 동일하게 .yaml file에 해당 dependencie를 추가해 줍니다.
dependencies :
http : ^1.2.1
3. 그렇다면 이제 다음과 같이 uri과 params, header를 통해 통신할 수 있습니다.
const String apiKey = 'KaKaoAK ${ Rest key } ' ;
final Map < String , String > queryParams = {
'y' : ' ${ position . latitude } ' ,
'x' : ' ${ position . longitude } ' ,
'radius' : '20000' ,
'query' : '카카오 프렌즈'
};
final uri = Uri . parse ( url ). replace ( queryParameters : queryParams );
final response = await http . get (
uri ,
headers : {
'Authorization' : apiKey ,
},
);
if ( response . statusCode == 200 ) {
final data = jsonDecode ( response . body );
log ( 'Response data: $ data ' );
} else {
log ( 'Request failed with status: ${ response . statusCode } .' );
}
}
통신의 결과 log를 확인해보자
결과
[log] Request failed with status: 401.
... ??
Flutter Code로 실행한 결과 권한이 없음 이였다. 하지만 이는 domain과 params가 잘못된 경우도 포함되므로 다음과 같은 시도를 하였다. ( javascript로 추가 검증시에 발견 )
1. url = https://dapi.kakao.com/v2/local/search/keyword 2. parms를 필수 param인 query만 두고 작성 3. --data-urlencode를 위한 Uri.encodeComponent(keyword) 4. Kakao문서의 SDK 추가 5. 네이트비 앱 키 등록 6. Admin 키 사용 7. 보낸 domain, header, params 재 확인 ( 텍스트 비교기로 확인 )
( 혹시나 RestApi + Flutter http 로 되는 사람이 있으면 댓글 부탁드립니다. )
때문에 이 코드를 JavaScript로 변환시켜 Node.js로 실행시켜보니 200(Ok)의 결과와 함께 데이터가 왔다..
전체 코드 ( Flutter )
import 'dart:convert' ;
import 'dart:developer' ;
import 'package:flutter/material.dart' ;
import 'package:geolocator/geolocator.dart' ;
import 'package:http/http.dart' as http ;
class TestPage extends StatefulWidget {
const TestPage ({ super . key });
@ override
State < TestPage > createState () => _TestPageState ();
}
class _TestPageState extends State < TestPage > {
Future < void > fetch () async {
// 현재의 위도 경도 위치를 가져옴
Position position = await Geolocator . getCurrentPosition (
desiredAccuracy : LocationAccuracy . high );
const String apiKey = 'KaKaoAK ${ Rest key } ' ;
final Map < String , String > queryParams = {
'y' : ' ${ position . latitude } ' ,
'x' : ' ${ position . longitude } ' ,
'radius' : '20000' ,
'query' : '카카오 프렌즈'
};
final uri = Uri . parse ( url ). replace ( queryParameters : queryParams );
final response = await http . get (
uri ,
headers : {
'Authorization' : apiKey ,
},
);
if ( response . statusCode == 200 ) {
final data = jsonDecode ( response . body );
log ( 'Response data: $ data ' );
} else {
log ( 'Request failed with status: ${ response . statusCode } .' );
}
}
@ override
void initState () {
super . initState ();
fetch ();
}
@ override
Widget build ( BuildContext context ) {
return Scaffold (
appBar : AppBar (
title : const Text ( "테스트 페이지" ),
),
body : const Center (
child : Text ( "지도 api 테스트중 입니다." ),
),
);
}
}
마치며.. 이 문제도 문제인데, KEY 의 보안 문제 때문에 클라우드 서비스를 통해 데이터를 전달 받는 방식으로 다음 포스팅을 하려고 한다. 다음에는 AWS를 활용하여 데이터를 전달받고 지도에 마커를 등록하는 글로 찾아오겠습니다.