C# 공공데이터 포털 오픈 API 자료 이용하는 방법

먼저, 공공데이터포털 사이트(https://www.data.go.kr/)에 가입을 하고, 이용하고자 하는 서비스(여기서는 기상청 날씨예보 정보를 기준으로 작성함) 등록, 서비스 키 발행을 선행해 두어야만 API서비스 사용이 가능해 진다. 또한, 해당 서비스에서 제공하는 API활용가이드도 다운로드 받아 참조할 수 있도록 준비!!!

자~ API서비스 사용 준비가 되었다면, Test를 위해 Visual Studio에서 Console프로젝트를 생성한다.

이후 아래 순으로 코딩해 나가면 끝.
  1. 먼저 main() 안에 해당 API에 접속할 url을 생성한다.
     방법은 API활용 가이드를 우선 참조하고 이하 코드로 작성하면 된다.
     나는 "동네예보조회" 서비스를 이용해 보겠다.
   
번호
API(국문)
상세기능명(영문)
상세기능명(국문)
1
동네예보 조회서비스
getUltraSrtNcst
초단기실황조회
2
getUltraSrtFcst
초단기예보조회
3
getVilageFcst
동네예보조회
4
getFcstVersion
예보버전조회
 
상세기능 번호
1
상세기능 유형
조회 (목록)
상세기능명(국문)
초단기실황조회
상세기능 설명
실황정보를 조회하기 위해 발표일자, 발표시각, 예보지점 X 좌표, 예보지점 Y 좌표의 조회 조건으로 자료구분코드, 실황값, 발표일자, 발표시각, 예보지점 X 좌표, 예보지점 Y 좌표의 정보를 조회하는 기능
Call Back URL
http://apis.data.go.kr/1360000/VilageFcstInfoService/
최대 메시지 사이즈
[1764] byte
평균 응답 시간
[100] ms
초당 최대 트랙잭션
[30] tps

위 표의 "Call Back URL"이 기본 접속 url 이고,  여기에 동네예보조회의 상세기능명(getVilageFcst)을 추가하고, 이하 요청 메세지 명세대로 string 값을 작성한다.

*요청 메시지 명세

항목명(영문)
항목명(국문)
항목크기
항목구분
샘플데이터
항목설명
serviceKey
인증키
100
1
인증키
(URL Encode)
공공데이터포털에서 발급받은 인증키
numOfRows
한 페이지 결과 수
4
1
10
한 페이지 결과 수
Default: 10
pageNo
페이지 번호
4
1
1
페이지 번호
Default: 1
dataType
응답자료형식
4
0
XML
요청자료형식(XML/JSON)
Default: XML
base_date
발표일자
8
1
20151201
15 12 1일 발표
base_time
발표시각
4
1
0600
06시 발표(정시단위)
-매시각 40분 이후 호출
nx
예보지점 X 좌표
2
0
18
예보지점의 X 좌표값
*별첨 엑셀 자료 참조
ny
예보지점 Y 좌표
2
0
1
예보지점의 Y 좌표값
*별첨 엑셀 자료 참조

전체 string값은 이하와 같이 작성하면 됨!!

 string url = "http://apis.data.go.kr/1360000/VilageFcstInfoService/";
            url += "getVilageFcst"
            url += "?ServiceKey=" + "인증받은 서비스 키 값"
            url += "&numOfRows=10";             // 한페이지 결과 수(Default : 10)
            url += "&pageNo=1";                 // 페이지 번호(Default : 1)
            url += "&dataType=XML";             // 받을 자료형식(XML, JSON)
            url += "&base_date=" + base_date;   // 요청 날짜(yyMMdd)
            url += "&base_time=" + base_time;   // 요청 시간(HHmm)
            url += "&nx=XXX";                    // 요청 지역 x좌표
            url += "&ny=XXX";                   // 요청 지역 y좌료

   * nx, ny값은 공공데이터포털에서 해당서비스 사용 시 오픈API활용 가이드와 함께 제공되는 격자 위경도 엑셀자료를 참조한다.

  2. API에 자료요청과 결과 받기
   HttpWebRequest로 API요청하고, HttpWebResponse와 Stream을 이용해 결과를 받아       온다.
   코드는 이와 같이 작성!!
   var request = (HttpWebRequest)WebRequest.Create(url);
   request.Method = "GET";
   string results = string.Empty;
   HttpWebResponse response;
   using (response = request.GetResponse() as HttpWebResponse)
   {
        StreamReader reader = new StreamReader(response.GetResponseStream());
        results = reader.ReadToEnd();
   }

  3. 받아온 결과를 xml형식으로 파싱하여, xml데이터에 접근할 수 있게 한다.
   XmlDocument xml = new XmlDocument();
   xml.LoadXml(results);
   XmlNodeList xmResponse = xml.GetElementsByTagName("response");
   XmlNodeList xmlList = xml.GetElementsByTagName("item");
 
   * 상기 "response", "item"은 xml데이터에 접근할 element 임.
     이하는 응답되는 자료의 xml 데이터 형식과 명세 이니 참조할 것.
   < response >
        < header >
              < resultCode > 00 </ resultCode >
              < resultMsg > NORMAL_SERVICE </ resultMsg >
         </ header >
         < body >
              < dataType > XML </ dataType >
              < items >
                  < item >
                      < baseDate > 20200228 </ baseDate >
                      < baseTime > 0500 </ baseTime >
                      < category > POP </ category >
                      < fcstDate > 20200228 </ fcstDate >
                      < fcstTime > 0900 </ fcstTime >
                      < fcstValue > 30 </ fcstValue >
                      < nx > 1 </ nx >
                      < ny > 1 </ ny >
                  </ item >
              < /items >
         < /body >
   < /response >
응답 메시지 명세

항목명(영문)
항목명(국문)
항목크기
항목구분
샘플데이터
항목설명
numOfRows
한 페이지 결과 수
4
1
1
한 페이지당 표출
데이터 수
pageNo
페이지 번호
4
1
1
페이지 수
totalCount
데이터 총 개수
10
1
1
데이터 총 개수
resultCode
응답메시지 코드
2
1
00
응답 메시지코드
resultMsg
응답메시지 내용
100
1
NORMAL SERVICE
응답 메시지 설명
dataType
데이터 타입
4
1
XML
응답자료형식 (XML/JSON)
baseDate
발표일자
8
1
20151201
15 12 1일 발표
baseTime
발표시각
6
1
0600
06시 발표(매 정시)
nx
예보지점 X 좌표
2
0
59
입력한 예보지점 X 좌표
ny
예보지점 Y 좌표
2
0
125
입력한 예보지점 Y 좌표
category
자료구분코드
3
1
LGT
자료구분코드
* 하단 코드값 정보 참조
obsrValue
실황 값
2
0
0
RN1, T1H, UUU, VVV, WSD
실수로 제공
* 하단 코드값 정보 참조

  4. 자~ 여기까지 준비가 되었다면, xml데이터에서 사용하고 자 정보를 사용해 보자!!
     나는 강수형태와 하늘상태 정보를 사용해 보겠다. 일단, 이하 코드값 정보를 참조하자!!
예보구분
항목값
항목명
단위
압축bit
동네예보
POP
강수확률
%
8
PTY
강수형태
코드값
4
R06
6시간 강수량
범주 (1 mm)
8
REH
습도
%
8
S06
6시간 신적설
범주(1 cm)
8
SKY
하늘상태
코드값
4
T3H
3시간 기온
10
TMN
아침 최저기온
10
TMX
낮 최고기온
10
UUU
풍속(동서성분)
m/s
12
VVV
풍속(남북성분)
m/s
12
WAV
파고
M
8
VEC
풍향
m/s
10
WSD
풍속
1
10


















- 하늘상태(SKY) 코드 : 맑음(1), 구름많음(3), 흐림(4)
* 구름조금(2) 삭제 (2019.06.4)
- 강수형태(PTY) 코드 : 없음(0), (1), /(2), (3), 소나기(4)

여기서 비/눈은 비와 눈이 섞여 오는 것을 의미 (진눈개비)

  상기 표를 참조하여 이하와 같이 작성하면 해당 xml데이터를 사용할 수 있다.
           foreach (XmlNode node in xmResponse)
            {
                if (node["header"]["resultMsg"].InnerText.Equals("NORMAL_SERVICE"))
                {
                    foreach (XmlNode node1 in xmlList)
                    {
                        if (node1["category"].InnerText.Equals("SKY"))
                        {
                            switch (node1["fcstValue"].InnerText)
                            {
                                case "1":
                                    Console.WriteLine("맑음");
                                    break;
                                case "3":
                                    Console.WriteLine("구름많음");
                                    break;
                                case "4":
                                    Console.WriteLine("흐림");
                                    break;
                                default:
                                    Console.WriteLine("해당 자료가 없습니다.");
                                    break;
                            }
                        }

                        if (node1["category"].InnerText.Equals("PTY"))
                        {
                            switch (node1["fcstValue"].InnerText)
                            {
                                case "0":
                                    Console.WriteLine("없음");
                                    break;
                                case "1":
                                    Console.WriteLine("비");
                                    break;
                                case "2":
                                    Console.WriteLine("비/눈/진눈개비");
                                    break;
                                case "3":
                                    Console.WriteLine("눈");
                                    break;
                                case "4":
                                    Console.WriteLine("소나기");
                                    break;
                                default:
                                    Console.WriteLine("해당 자료가 없습니다.");
                                    break;
                            }
                        }
                    }


*** 참조 : 전체소스

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Xml;

namespace WeatherAPITest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(DateTime.Now.ToString("yyyyMMdd"));
            Console.WriteLine(DateTime.Now.ToString("HHmm"));

            int time = int.Parse(DateTime.Now.ToString("HH"));
            string base_date = DateTime.Now.ToString("yyyyMMdd");

            string base_time;
            // API에 요청할 base_time 설정 : 오픈API활용가이드 참조
            switch (time)
            {
                case 2:
                case 3:
                case 4:
                    base_time = "0200";
                    break;
                case 5:
                case 6:
                case 7:
                    base_time = "0500";
                    break;
                case 8:
                case 9:
                case 10:
                    base_time = "0800";
                    break;
                case 11:
                case 12:
                case 13:
                    base_time = "1100";
                    break;
                case 14:
                case 15:
                case 16:
                    base_time = "1400";
                    break;
                case 17:
                case 18:
                case 19:
                    base_time = "1700";
                    break;
                case 20:
                case 21:
                case 22:
                    base_time = "2000";
                    break;
                case 23:
                case 24:
                case 1:
                    base_time = "2300";
                    break;

                default:
                    base_time = "0500";
                    break;
            }

            // API 요청 URL 작성
            string url = "http://apis.data.go.kr/1360000/VilageFcstInfoService/getVilageFcst"; // URL(getUltraSrtNcst : 초단기실활조회, getUltraSrtFcst : 초단기예보조회, getVilageFcst : 동네예보조회, getFcstVersion : 예보버전조회
            url += "?ServiceKey=" + "인증받은 서비스 키"; // Service Key
            //url += "&ServiceKey=-";
            url += "&numOfRows=10";             // 한페이지 결과 수(Default : 10)
            url += "&pageNo=1";                 // 페이지 번호(Default : 1)
            url += "&dataType=XML";             // 받을 자료형식(XML, JSON)
            //url += "&ftype=ODAM";
            url += "&base_date=" + base_date;   // 요청 날짜(yyMMdd)
            url += "&base_time=" + base_time;   // 요청 시간(HHmm)
            url += "&nx=54";                    // 요청 지역 x좌표
            url += "&ny=123";                   // 요청 지역 y좌료

            Console.WriteLine(url);

            /* XmlReader를 이용한 결과 수신 처리 방법
            XmlReader reader = XmlReader.Create(url);
            string valueStr = string.Empty;
            while(reader.Read())
            {
                switch(reader.NodeType)
                {   
                    case XmlNodeType.Text:
                            valueStr += reader.Value;
                            valueStr += "/";
                        break;
                }
            }
            string[] temmpStr = valueStr.Split('/');

            Console.WriteLine(valueStr);
            Console.WriteLine(reader.Value);
            */


            // HttpWebRequest 이용한 응답 수신 방법
            var request = (HttpWebRequest)WebRequest.Create(url);   // 요청 URL을 기준으로 HTTP요청 인스턴스 생성
            request.Method = "GET"; // 방법은 GET(요청)으로 설정

            string results = string.Empty;
            HttpWebResponse response;   // HTTP응답 인스턴스 생성
            using (response = request.GetResponse() as HttpWebResponse) // 응답 요청
            {
                StreamReader reader = new StreamReader(response.GetResponseStream());   // stream방식으로 결과 수시을 위한 인스턴스 생성
                results = reader.ReadToEnd();   // 수신된 결과 읽어오기
            }

            Console.WriteLine(results);

            /* XML 응답자료 형식 : 참조
            < response >
                < header >
                    < resultCode > 00 </ resultCode >
                    < resultMsg > NORMAL_SERVICE </ resultMsg >
                </ header >
                < body >
                    < dataType > XML </ dataType >
                    < items >
                        < item >
                            < baseDate > 20200228 </ baseDate >
                            < baseTime > 0500 </ baseTime >
                            < category > POP </ category >
                            < fcstDate > 20200228 </ fcstDate >
                            < fcstTime > 0900 </ fcstTime >
                            < fcstValue > 30 </ fcstValue >
                            < nx > 1 </ nx >
                            < ny > 1 </ ny >
                        </ item >
                    < /items >
                < /body >
            < /response >
            */

            // 수신된 XML형식의 데이터를 컨트롤하기위해 XmlDocument 인스턴스를 생성
            XmlDocument xml = new XmlDocument();
            xml.LoadXml(results);   // Stream결과를 XML형식으로 읽어오기
            XmlNodeList xmResponse = xml.GetElementsByTagName("response");  // <response></response> 기준으로 node 생성
            XmlNodeList xmlList = xml.GetElementsByTagName("item"); // <item></item> 기준으로 node 생성

            foreach (XmlNode node in xmResponse)    // xml의 <response> 값 읽어 들이기
            {
                if (node["header"]["resultMsg"].InnerText.Equals("NORMAL_SERVICE")) // 정상 응답일 경우
                {
                    foreach (XmlNode node1 in xmlList)  // <item> 값 읽어 들이기
                    {
                        if (node1["category"].InnerText.Equals("SKY"))  // 하늘상태일 경우
                        {
                            switch (node1["fcstValue"].InnerText)
                            {
                                case "1":
                                    Console.WriteLine("맑음");
                                    break;
                                case "3":
                                    Console.WriteLine("구름많음");
                                    break;
                                case "4":
                                    Console.WriteLine("흐림");
                                    break;
                                default:
                                    Console.WriteLine("해당 자료가 없습니다.");
                                    break;
                            }
                        }

                        if (node1["category"].InnerText.Equals("PTY"))  // 강수형태일 경우
                        {
                            switch (node1["fcstValue"].InnerText)
                            {
                                case "0":
                                    Console.WriteLine("없음");
                                    break;
                                case "1":
                                    Console.WriteLine("비");
                                    break;
                                case "2":
                                    Console.WriteLine("비/눈/진눈개비");
                                    break;
                                case "3":
                                    Console.WriteLine("눈");
                                    break;
                                case "4":
                                    Console.WriteLine("소나기");
                                    break;
                                default:
                                    Console.WriteLine("해당 자료가 없습니다.");
                                    break;
                            }
                        }
                    }
                }
                else
                {
                    string apiErrorMsg = String.Empty;

                    // API 응답 에러 메세지 조사
                    apiErrorMsg = node["header"]["resultMsg"].InnerText switch
                    {
                        "APPLICATION_ERROR" => "어플리케이션 에러",
                        "DB_ERROR" => "데이터베이스 에러",
                        "NODATA_ERROR" => "데이터 없음",
                        "HTTP_ERROR" => "HTTP 에러",
                        "SERVICETIME_OUT" => "서비스 연결실패",
                        "INVALID_REQUEST_PARAMETER_ERROR" => "잘못된 요청 파라메터",
                        "NO_MANDATORY_REQUEST_PARAMETERS_ERROR" => "필수요청 파라메터가 없음",
                        "NO_OPENAPI_SERVICE_ERROR" => "해당 오픈 API서비스가 없거나 폐기됨",
                        "SERVICE_ACCESS_DENIED_ERROR" => "서비스 접근 거부",
                        "TEMPORARILY_DISABLE_THE_SERVICEKEY_ERROR" => "일시적으로 사용할 수 없는 서비스 키",
                        "LIMITED_NUMBER_OF_SERVICE_REQUESTS_EXCEEDS_ERROR" => "서비스 요청제한횟수 초과",
                        "SERVICE_KEY_IS_NOT_REGISTERED_ERROR" => "등록되지 않은 서비스 키",
                        "DEADLINE_HAS_EXPIRED_ERROR" => "기한 만료된 서비스 키",
                        "UNREGISTERED_IP_ERROR" => "등록되지 않은 IP",
                        "UNSIGNED_CALL_ERROR" => "서명되지 않은 호출",
                        "UNKNOWN_ERROR" => "기타에러",
                        _ => "해당하는 에러가 존재하지 않음",
                    };

                    // API 응답 에러 메세지 출력
                    Console.WriteLine(apiErrorMsg);
                }
            }            
        }
    }
}

댓글

가장 많이 본 글