개발/Unity

[Unity] 공공데이터 API (REST) 연동하는 방법 - (2)

센솔 2020. 7. 1. 11:59

1편에 이어 글을 계속 이어나간다.

 

지난번 포스팅에서는 공공데이터포털에 가입해 승인신청을 받는 과정까지를 다루었다.

 

승인신청이 정상적으로 완료되었다면 다음과 같은 화면을 볼 수 있을 것이다. 

(공공데이터포털-마이페이지-활용중인 서비스 클릭)

 

인증키는 노출되지 않게끔 블라인드 처리하였다

위 화면에서 눈여겨볼 부분은 인증키, 데이터포맷, 참고문서 이다. 

 

우선 포스팅을 읽는 사람들마다 불러오려는 데이터가 조금씩 다를 수 있기 때문에,

각자의 서비스 정보에 포함된 참고문서를 정독하는 것을 권장한다.

 

1. 참고문서에서 내가 불러오려는 데이터를 확인하기

우선 참고문서를 열어 목차를 훑어본다. 내가 불러오려는 데이터가 정확히 어떤것인지 확인하기 위해서이다.

예를들어, 날씨를 다루는 API가 있더라도 그안에 '측정소별 강수량', '월간 평균 강수량' 등 다양한 통계가 있기 때문이다.

 

필자가 불러오려는 정보는 시, 도별로 분류된 미세먼지(pm) 지수이다. 여러 서비스의 설명을 읽어보니, '대기오염정보 조회 서비스' 가 가장 적합한 데이터셋으로 보였다. 

 

요청 / 응답 메시지 예제를 읽어보니 더욱 확실해졌다. 가장 위에 URL 링크 형식이 나와있고, 지역구에 따라 'pm10value', 'pm25value' 등 정보를 불러올 수 있는게 확인된다. 이제부터 본격적으로 활용해보자.

 

2. 인증키 확인 및 URL 불러오기

발급받은 인증키와 서비스 상태를 확인하려면 간단히 참고문서에 나와있는 URL 링크를 인터넷 주소에 붙여넣으면 된다.

 

다른 부분은 그대로 냅두고, 서비스키 부분만 자신이 발급받은 인증키를 넣어주면 된다. 인증키는 앞서 언급한 것과 같이 공공데이터 포털-마이페이지-개발계정 상세보기에서 확인할 수 있다. 

 

위 URL을 크롬 주소창에 붙여넣으면 다음과 같은 화면을 볼 수 있다. 종로구의 실시간 미세먼지 정보를 XML 형식으로 출력하는 모습을 확인할 수 있다! 

 

 필자는 참고문서에서 &_returnType=json을 URL 뒤에 붙이면 JSON 형식으로도 가져올 수 있다는 설명이 있었기 때문에, 한번 JSON 형식으로도 불러와보겠다. 

역시 JSON 형식으로 제대로 불러오는 모습을 볼 수 있다. 필자는 JSON 형식의 데이터로 유니티에 불러오도록 하겠다.

3. 유니티를 켜자!

이제 유니티를 연 다음, 빈 게임오브젝트를 만들어 API 매니저라는 이름을 붙이고 스크립트를 하나 생성해주겠다.

 

그냥 게임오브젝트 만든다음 오브젝트에 스크립트를 갖다 끌어붙여도 된다

스크립트에는 다음 내용을 입력해주도록 한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class LoadAPI : MonoBehaviour
{
    string jsonResult;
    bool isOnLoading = true;

    void Start()
    {
        StartCoroutine(LoadData());
    }


    IEnumerator LoadData() //json 문자열 받아오기
    {
        string GetDataUrl = "http://openapi.airkorea.or.kr/openapi/services/rest/ArpltnInforInqireSvc/getCtprvnMesureSidoLIst?sidoName=%EC%84%9C%EC%9A%B8&searchCondition=DAILY&pageNo=1&numOfRows=25&ServiceKey=(내 인증키 입력하는 칸)&_returnType=json";
        using (UnityWebRequest www = UnityWebRequest.Get(GetDataUrl))
        {
            //www.chunkedTransfer = false;
            yield return www.Send();
            if (www.isNetworkError || www.isHttpError) //불러오기 실패 시
            {
                Debug.Log(www.error);
            }
            else
            {
                if (www.isDone)
                {
                    isOnLoading = false;
                    jsonResult =
                        System.Text.Encoding.UTF8.GetString(www.downloadHandler.data);
                    Debug.Log(jsonResult);
                }
            }
        }
    }

}

 UnityEngine.Networking을 추가한 후, UnityWebRequest의 Get 명령을 이용해 웹데이터를 string 형식으로 파싱해오는 코드이다. 실행해보면 간단히 웹페이지 내용 전체를 파싱해온 결과를 얻을 수 있다.

 

GetDataUrl에는 웹페이지에 붙여넣은 그 주소를 그대로 옮겨적으면 된다. 

아까 웹페이지에서 보았던 내용과 같은것을 알 수 있다! 이로써 웹페이지 정보를 유니티와 연결시키는 데에 성공했다.

이제 자신이 원하는 내용만을 추출하는 과정만이 남았다. 

 

우리에게는 두 가지 선택지가 있다.

 

방법 1. C# 기본 문법을 이용해 문자열을 자르고 나누어 처리한다.

방법 2. Json 파싱에 최적화된 외부 라이브러리를 적용해 처리한다.

 

방법 1의 경우, 파싱해온 데이터가 간단한 형태라면 고려해볼 수 있다. 많고많은 문자열 가운데 내가 원하는 정보가 한 문장 정도일 때에는 이렇게 해도 상관없을 것 같다.

 

그러나 필자는 지역구별로 여러개의 미세먼지 데이터를 불러오고 싶을 뿐더러, 정렬해서 보기 좋게 나타내고 싶다.

따라서 LitJson 이라는 Json 파싱 라이브러리를 불러와서 진행해보겠다.

 

(추가: 유니티 5.3버전 이상부터 외부 라이브러리 없이도 Json 형식의 데이터포맷을 파싱할 수 있는 유틸리티가 추가되었다. 후술할 방법 대신 자체 유틸리티를 사용해도 무방하다)

 

LitJson 홈페이지

 

LitJSON - Home

What is LitJSON? A .Net library to handle conversions from and to JSON (JavaScript Object Notation) strings. LitJSON is written in C#, and it’s intended to be small, fast and easy to use. It's quick and lean, without external dependencies. Just a few cla

litjson.net

간단히 LitJson.dll을 다운받은 후에, 유니티 Asset 폴더 안 Plugin이라는 폴더를 만들어 그안에 넣어주면 된다.

LitJson 적용법은 다른 블로그에도 자세히 설명이 되어있으니 구글링해봐도 좋을 것 같다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using LitJson;

모든 적용이 끝났다면 스크립트에 LitJson을 추가시키도록 한다. 

    public void InitData()
    {
        JsonData ItemData = JsonMapper.ToObject(jsonResult);

        string CityName = ItemData["list"][0]["cityName"].ToString(); //도시 이름
        string pm10Level = ItemData["list"][0]["pm10Value"].ToString(); //미세먼지 농도
	//지역구는 가나다순, [0]은 강남구
        Debug.Log(CityName);
        Debug.Log(pm10Level);
    }

    IEnumerator LoadData() //json 문자열 받아오기
    {
        string GetDataUrl = "http://openapi.airkorea.or.kr/openapi/services/rest/ArpltnInforInqireSvc/getCtprvnMesureSidoLIst?sidoName=%EC%84%9C%EC%9A%B8&searchCondition=DAILY&pageNo=1&numOfRows=25&ServiceKey=6KaVphDzYMF1%2Bma5Q1Y%2FR1%2F4preJiHc50QLqIFBO89GIigVXN3i3ZQCSZHtagpP1NL%2FgnpIOpV2Z6fn%2FvDmVEQ%3D%3D&_returnType=json";
        using (UnityWebRequest www = UnityWebRequest.Get(GetDataUrl))
        {
            //www.chunkedTransfer = false;
            yield return www.Send();
            if (www.isNetworkError || www.isHttpError) //불러오기 실패 시
            {
                Debug.Log(www.error);
            }
            else
            {
                if (www.isDone)
                {
                    isOnLoading = false;
                    jsonResult =
                        System.Text.Encoding.UTF8.GetString(www.downloadHandler.data);
                    InitData();
                }
            }
        }
    }

InitData() 함수를 만들어 전체 문자열 중 필요한 부분만을 추출하는 기능을 만들었다.

LitJson이 제공하는 JsonData 데이터 형식의 객체 ItemData를 만들고, 전체 문자열 내용을 넣어주는 부분을 확인할 수 있다. 이후 ItemData의 뎁스("list"-지역구-"데이터이름": 3차원) 에 맞추어 Key값(cityname, pm10value)을 받아오는 모습을 볼 수 있다.

 

이렇게 원하는 데이터만을 지정해 실시간으로 유니티에 연동해오는 것에 성공했다.

 

위 사진은 실제로 미세먼지 API를 게임플레이에 적용한 모습이다.

미세먼지 지수에 따라 오름차순 정렬한 뒤, 1부터 5까지의 레벨로 나누어 지역구의 색깔을 다르게 표현했다.

 

공공데이터포털은 다양한 API를 제공하고 있다. 이처럼 실제 게임플레이와 연동시켜 응용한다면 창의적이고 실감나는 게임을 만드는 데에 적극 활용할 수 있을 것이라고 생각한다.

 

<참고한 자료>

https://www.youtube.com/watch?v=9rPJeRF7S_8