Flutter 개발 일지

KaKao Map Rest API + Flutter 사용해보기 ( http 통신 ) - 1

anycoding 2024. 5. 24. 22:08
반응형
해당 게시글에서는 지도 화면이 아닌 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를 활용하여 데이터를 전달받고 지도에 마커를 등록하는 글로 찾아오겠습니다.

 

반응형