본문 바로가기
앱 프로그래밍/flutter

플러터로 기상청 날씨 앱 만들기 일지 2. 데이터 연동(기상청 API)

by 청량리 물냉면 2022. 1. 5.
반응형

geolocator을 통해 현재 내 위치 정보 불러오기

 

https://velog.io/@jintak0401/FlutterDart-%EC%97%90%EC%84%9C%EC%9D%98-Future-asyncawait

 

Flutter/Dart 에서의 Future, async/await

Flutter 와 Dart 를 공부하면서 깨달은 Future, async / await 에 대한 설명과 고민에 대한 답을 작성한 포스트입니다.

velog.io

 

 

API 신청

공공 데이터 포털(https://www.data.go.kr/index.do)에서 api를 신청했다. 

나는 앱에서 날씨 정보와 미세먼지 정보를 함께 보여줄 것이기 때문에 기상청 동네예보 api와 에어코리아 대기오염 정보 api 2개를 신청했다. 

 

날씨

기상청 단기예보(https://www.data.go.kr/data/15084084/openapi.do)

 

기상청_단기예보 ((구)_동네예보) 조회서비스

초단기실황, 초단기예보, 단기((구)동네)예보, 예보버전 정보를 조회하는 서비스입니다. 초단기실황정보는 예보 구역에 대한 대표 AWS 관측값을, 초단기예보는 예보시점부터 6시간까지의 예보를,

www.data.go.kr

 

미세먼지

에어코리아 대기오염정보(https://www.data.go.kr/tcs/dss/selectApiDataDetailView.do?publicDataPk=15073861)

 

한국환경공단_에어코리아_대기오염정보

각 측정소별 대기오염정보를 조회하기 위한 서비스로 기간별, 시도별 대기오염 정보와 통합대기환경지수 나쁨 이상 측정소 내역, 대기질(미세먼지/오존) 예보 통보 내역 등을 조회할 수 있다.

www.data.go.kr

 

api 키는 신청하자마자 발급되었다. 혹시나 싶어 위치기반 서비스 사업 신고에 대한 정보도 찾아보았다. 

위치기반 서비스 사업 신고

전자민원 센터를 이용한 위치정보사업자 허가 및 위치기반서비스사업자 신고 안내(방송통신위원회)

 o (사업자 유형) 위치기반 검색, 위치주변 정보 제공, 친구 찾기, 물류, 차량 관제, LBS 광고 등을 제공하는 서비스로 스마트폰 어플리케이션 이용 사업자가 다수                   → 방통위 신고대상   
※ 스마트폰 GPS를 활용하여 어플리케이션으로만 서비스하는 사업자의 경우, 수집된 위치정보가 스마트폰 OS 사업자에 의해 수집된 후 어플리케이션 서비스사업자가 이를 활용하는 것에 해당하므로 위치기반서비스사업에 해당   
- 단, 이용자 위치정보의 저장여부와 관계없이 사업자 서버로 이용자의 위치정보가 “전송”되는 경우만 신고 대상이며, 이용자 단말기에서만 활용하거나 개인위치정보를 대상으로 하지 않는 경우는 신고 대상이 아님

나는 단말기에서만 사용자 정보를 사용할 것이기 때문에 신고하지 않았다.  

 

 

geolocator을 통해 불러온 내 위치의 경도, 위도를 x, y좌표로 변경하기

 

기상청 api정보는 위도 경도가 아닌 x, y 좌표 기준으로 한다. 

geolocator 위도 경도 -> x, y 좌표 변경하는 코드는 아래 블로그를 참고했다.  

 

https://idlecomputer.tistory.com/320

 

[Flutter,Dart](신)동네예보정보조회서비스 기상청 API,위도 경도->좌표

이번에 공공 데이터 포털 의 API 중 동네 예보 정보 조회 서비스 API 를 사용할 일이 있어서 사용 하다가 동네를 찾을때 위도 경도를 사용하는것이 아닌 기상청 만의 특정 좌표를 사용 하더라구요.

idlecomputer.tistory.com

위도(latitude)는 Y, 경도(longitude)는 X좌표에 대응된다.

 

 

정보가 알맞게 변경되었는지 확인하기 위해서는 아래 사이트를 이용했다. 

https://fronteer.kr/service/kmaxy

 

기상청 격자정보 - 위경도 변환 : Grid XY - Lat, Lon

데이터형식 : 위도, 경도 37.579871128849334, 126.98935225645432 35.101148844565955, 129.02478725562108 33.500946412305076, 126.54663058817043

fronteer.kr

 

 

API 호출

loading.dart

Network network = Network('http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtNcst?serviceKey=$apiKey&numOfRows=10&pageNo=1&base_date=20220105&base_time=0600&nx=55&ny=127&dataType=JSON');

 

Network.dart

import 'package:http/http.dart' as http;
import 'dart:convert';

class Network {
  final String weatherUrl;
  Network(this.weatherUrl);

  Future<dynamic> getWeatherData() async {
    http.Response response = await http.get(Uri.parse(weatherUrl));
    if(response.statusCode == 200) {
      String jsonData = response.body;
      var parsingData = jsonDecode(jsonData); //json형식 문자열을 배열 또는 객체로 변환하는 함수
      return parsingData;
    }
  }

}

위와 같이 작성하였으나, JSON 데이터를 올바로 파싱하지 못하는 오류가 발생했다. (파싱한 json 값을 print했을 때 null만 출력됨)

이를 해결하기 위해

var parsingData = jsonDecode(jsonData);

위 코드를

var parsingData = await json.decode(json.encode(jsonData));

위와 같이 수정하였다.

추가로 기상청에서 제공한 일반 인증키 두개 (Decoding, Encoding)를 모두 사용해 보면서 둘 중 올바른 값이 출력되는 키를 사용했다. 

I/flutter (23727): {"response":{"header":{"resultCode":"00","resultMsg":"NORMAL_SERVICE"},"body":{"dataType":"JSON","items":{"item":[{"baseDate":"20220105","baseTime":"0600","category":"PTY","nx":55,"ny":127,"obsrValue":"0"},{"baseDate":"20220105","baseTime":"0600","category":"REH","nx":55,"ny":127,"obsrValue":"56"},{"baseDate":"20220105","baseTime":"0600","category":"RN1","nx":55,"ny":127,"obsrValue":"0"},{"baseDate":"20220105","baseTime":"0600","category":"T1H","nx":55,"ny":127,"obsrValue":"-8.3"},{"baseDate":"20220105","baseTime":"0600","category":"UUU","nx":55,"ny":127,"obsrValue":"-0.9"},{"baseDate":"20220105","baseTime":"0600","category":"VEC","nx":55,"ny":127,"obsrValue":"87"},{"baseDate":"20220105","baseTime":"0600","category":"VVV","nx":55,"ny":127,"obsrValue":"0"},{"baseDate":"20220105","baseTime":"0600","category":"WSD","nx":55,"ny":127,"obsrValue":"1"}]},"pageNo":1,"numOfRows":10,"totalCount":8}}}

다음과 같이 x좌표 55, y좌표 127 장소의 날씨 정보가 잘 출력되었다. 

 

 

출처: https://stackoverflow.com/questions/55671441/flutter-formatexception-unexpected-character-at-character-1

 

Flutter FormatException: Unexpected character (at character 1)

In flutter, i use a php file which returns a json response from a db query, but when i try to decode json i getting this error: E/flutter ( 8294): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhan...

stackoverflow.com

 

 

어제 날짜 불러오는 코드

DateTime.now().subtract(Duration(days:1));

 

내일 날짜 불러오는 코드

DateTime.now().add(Duration(days:1));

 

 

출처: https://stackoverflow.com/questions/61682959/the-date-of-yesterday-in-flutter

 

The date of yesterday in flutter

How can I calculate yesterdays date in dart/flutter? I have the date of today: DateTime.now() But I can't just do -1.

stackoverflow.com

 

 

오류 발생

type 'String' is not a subtype of type 'int' of 'index'

이 오류가 발생해서 더 이상 진도가 안 나갔다. 

var parsingData = await json.decode(json.encode(jsonData));

이 코드가 문제였던 듯(제이슨 파싱에 오류가 생겼었던 것 같다)

 

var parsingData = json.decode(jsonData);

이렇게 고치니까 오류는 사라졌다. 다만 값이 null로 뜸...  이제 이 오류 수정하러ㅣ....^^,,,ㅠ

 

jason을 4개 받아와서 연결했는데

type 'String' is not a subtype of type 'int' of 'index'

또 이 오류가 발생... 제이슨 파싱이 안 되거나 모종의 이유로 기상청 데이터를 받아오지 못했을 때 생기는 오류인 것 같다. ☞ 앱 제작을 거의 완료한 지금 보니 기상청 데이터는 받아왔지만, 그 데이터 내에서 내가 원하는 데이터를 뽑아오지 못할 때도 이 오류가 발생했다. 결국은 코드 오류다. 코드를 샅샅이 살펴서 원하는 json 값을 뽑아오도록 코드를 수정해야 한다. 

만 하루 동안 고민하다가 updateData 함수의 매개변수의 json data 변수와 실제 값을 세팅하는 변수가 똑같다는 것을 발견했다. 이런 실수를 하다니... 제이슨 데이터를 담아온 변수에다 새로운 추출한 제이슨 데이터를 세팅하고 있었다... 다행히 이제라도 발견하고 처리했다... 변수 이름 짓는 거 너무 어렵다...ㅠㅜㅠ 

 

 

*추가

앱 제작 막바지인 현재는 

var parsingData = jsonDecode(jsonData);

로 데이터를 잘 불러오고 있다. 오히려 인코딩을 한 번 하고 디코딩 했을 시 오류가 더 발생하는 듯 하다. json 파싱 오류의 원인은 아직도 명확히 발견하지 못했다. 😂

 

 

기상청 이용한 앱 만들기 오류, 기상청API 오류

계속되는 

[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: FormatException: Unexpected character (at character 1) E/flutter ( 1325): <OpenAPI_ServiceResponse> E/flutter ( 1325): ^ E/flutter ( 1325):

오류에 공공데이터 포털로 들어가 직접 json 데이터를 불러와 봤다.

아무리 해봐도 특정 시간 데이터 불러오기가 안 된다. 한 60번은 새로고침한 것 같은데. api 데이터 받아오는 시간도 오래 걸리는 데다 그 결과가 오류 메시지일 때는 정말 힘이 빠진다.

공공 데이터 포탈 문의하기 페이지에 들어가 보니 04번 에러로 문의하신 분들 많은 거 보니 나 혼자만의 문제는 아닌 듯 했다. 이대로 어플을 만들어봤자 배포 후에도 오류 생길 것 같고 다 만들어놓은 후에 오히려 유지보수만 더 까다로워질 것 같아 고민이다. 기상청 api 받아오기는 포기해야 할지...

 

 

+

다음 날 해보니 그래도 그나마 낫다.

인터넷을 찾아보니 너무 짧은 시간 내에 api 호출하면 또 오류가 생긴다고 해서 각 api를 불러올 때 0.5초 정도의 텀을 두고 불러왔다. ☞이 코드도 나중에는 다 삭제했다. 이 코드 없이도 기상청 api 컨디션이 좋으면 실행이 되고 아니면 실행이 안 된다.

주간 날씨는 나중에 하고 우선 미세먼지 초미세먼지 api 연결부터 해야겠다. 

반응형