Flutter - 위치 정보를 받아서 시, 구 를 화면에 띄우기

SonagiDev·2021년 8월 5일
1

Flutter

목록 보기
1/1

구현하고 싶은 기능

  1. 현재 위치를 위도, 경도로 받는다.
  2. 위도, 경도를 OO시 OO구로 변환한다.
  3. 변환된 주소를 화면에 나타낸다.

완성 화면

구현하기

1. 현재 위치를 위도, 경도로 받기

유튜브 코딩셰프님의 동영상을 참고했다.

https://www.youtube.com/watch?v=YqKMBQYZSmw&list=PLQt_pzi-LLfoOpp3b-pnnLXgYpiFEftLB&index=13&ab_channel=%EC%BD%94%EB%94%A9%EC%85%B0%ED%94%84

너무나 친절하게 잘 설명해준다. geolocator라는 플러그인을 활용한다. 전에 혼자 공부 했을 때는 권한 얻기(authentication?)부분에서 androidmanifest 파일과 info.plist 파일에 구문을 추가 할 때 위치를 정확히 몰라서 상당히 헤맸다. 아마 위 영상과 위 영상의 재생목록의 다음 영상 정도만 보더라도 현재 위치 구하는 것은 할 수 있을 것이다.

2. 위도, 경도를 시,구,동 주소로 변환하기

시작하기가 막막했던 부분이다. 네이버나 카카오의 api를 활용하면 되겠다는 생각이 들었는데 막상 api를 제대로 활용 해 본 적이 없어서 고생했다.
카카오와 네이버 api를 뒤지다가 네이버 클라우드 플랫폼에서 제공하는 reverse Geocoding API를 사용하기로 결정!

https://api.ncloud-docs.com/docs/ai-naver-mapsreversegeocoding-gc#

그런데 사용하려고 보니 뭐가 뭔지 하나도 모르겠다! 우선 네이버 맵 플러그인을 플러터에서 쓰기 위해 플러그인 install부터 했다.

네이버 맵 플러그인 공식 문서

https://pub.dev/packages/naver_map_plugin

설치에 유일한 한 줄기 빛이였던 글 하나
(marrrang 님께서 이 글을 보실지 모르겠지만 정말 압도적으로 감사합니다!)

https://marrrang.tistory.com/m/27

설치를 하고 나서 여러 정보를 뒤져가며 종합해서 어떻게든 콘솔에 띄우는 걸 성공시켰다.

Future<List> fetchData() async {
    Position position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.high);
	//현재위치를 position이라는 변수로 저장
    String lat = position.latitude.toString();
    String lon = position.longitude.toString();
	//위도와 경도를 나눠서 변수 선언
    print(lat);
    print(lon);
    // 잘 나오는지 확인!

    Response response = await get(
        Uri.parse(//이 부분이 코딩셰프님 영상과 차이가 있다. 플러터 버젼업이 되면서 이 메소드를 써야 제대로 uri를 인식한다.
            "https://naveropenapi.apigw.ntruss.com/map-reversegeocode/v2/gc?request=coordsToaddr&coords=${lon},${lat}&sourcecrs=epsg:4326&output=json"),
        headers: headerss);
        // 미리 만들어둔 headers map을 헤더에 넣어준다.
    String jsonData = response.body;
    //response에서 body부분만 받아주는 변수 만들어주공~
    print(jsonData);// 확인한번하고
    var myJson_gu =
        jsonDecode(jsonData)["results"][1]['region']['area2']['name'];
    var myJson_si =
        jsonDecode(jsonData)["results"][1]['region']['area1']['name'];

    List<String> gusi = [myJson_si, myJson_gu];

    return gusi; //구랑 시를 받아서 gusi라는 귀여운 이름으로 받는다...?
  }

네이버 공식 문서를 보면 요청 예시로 이런 코드가 있다.

curl "https://naveropenapi.apigw.ntruss.com/map-reversegeocode/v2/gc?request=coordsToaddr&coords=129.1133567,35.2982640&sourcecrs=epsg:4326&output=json&orders=legalcode,admcode" \
	-H "X-NCP-APIGW-API-KEY-ID: {애플리케이션 등록 시 발급받은 client id값}" \
	-H "X-NCP-APIGW-API-KEY: {애플리케이션 등록 시 발급받은 client secret값}" -v

나같은 초보 개발자 (더군다나 api를 처음 써보는..ㅜ)에겐 이걸 도대체 어떻게 쓰라는 거지?? 라는 생각이 들 뿐이다.. 열심히 구글링 한 결과 첫 번째 줄의 url은 get의 첫 번째 파라미터로 넘기면 되고(그 url 안에 여러 요청 parameter를 넣는다.), -H라고 되어있는 두 번째, 세 번째 줄을 map<String,String> 형태로 만들어 get의 두 번째 파라미터로 넘기면 된다.

쉽게 코드로 보자면 이런 형태이다.


Map<String,String> headerss = {
"X-NCP-APIGW-API-KEY-ID": "Client ID", // 개인 클라이언트 아이디
    "X-NCP-APIGW-API-KEY": "Client secret" // 개인 시크릿 키
}

Response response = get await(
	Uri.parse("url"),
    	headers: headerss;
    )

그리고 print(gusi);를 하면 이런 결과가 나온다.

flutter: [서울특별시, 서대문구]

3. 변환된 주소를 화면에 나타내기

gusi라는 리스트는 future를 통해서 나오기 때문에 futurebuilder를 통해 위젯에 나타내야 한다고 알고 있다. (아직 초보라 확실치는 않다..)

futurebuilder쓰는 방법을 검색해서 참조해서 코드를 짜 봤다.

https://eory96study.tistory.com/21
이 블로그를 참조해서 만든 코드이다.

 FutureBuilder(
                builder: (context, snapshot){
                  if (snapshot.hasData == false) {
                    return CircularProgressIndicator();
                  }
                  //error가 발생하게 될 경우 반환하게 되는 부분
                  else if (snapshot.hasError) {
                    return Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Text(
                        'Error: ${snapshot.error}',
                        style: TextStyle(fontSize: 15),
                      ),
                    );
                  }
                  else {
                    List ll = snapshot.data as List;

                    return Padding(

                      padding: const EdgeInsets.all(8.0),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Text(ll[0]),
                          Text("   "),
                          Text(ll[1]),
                        ],
                      ),
                    );
                  }
                },
                future: fetchData(),
              )

다만 snapshot.data에 인덱싱을 적용할 수가 없어서 ll이라는 snapshot.data를 list로 받는 새 list를 만들어서 인덱싱하였다. 거의 하드코딩 수준이었지만 일단 표현하는 데에는 성공했으니 응용하면 가능성이 무궁무진한듯!


후기
api를 쓰는 방법을 어느 정도 익혔으니 난 또 성장했다.. 엄청난 고통이 따르는 과정이었지만 뿌듯하다.

profile
꿈이 매우 큽니다

0개의 댓글