본문 바로가기
소소한 C# 지식

[C#]C# 기상청 API 연동하여 날씨 데이터 저장하기

by 해뤼맘 2022. 4. 26.
728x90
반응형

안녕하세요

기상청 날씨 API를 연동하여 날씨 데이터를 저장하는 코드를 포스팅하겠습니다.

 

1. 기상청 날씨 API 연동 문서 및 인증키 확인

 

공공데이터 포털

국가에서 보유하고 있는 다양한 데이터를『공공데이터의 제공 및 이용 활성화에 관한 법률(제11956호)』에 따라 개방하여 국민들이 보다 쉽고 용이하게 공유•활용할 수 있도록 공공데이터(Datase

www.data.go.kr

  • 기상청_단기예보 조회서비스를 검색하여 참고 문서에 있는 API 활용 가이드를 다운로드합니다.
  • 공공데이터 포털에 로그인 후 "활용신청" 버튼을 클릭하여 사용할 수 있는 인증키를 신청합니다.
  • API 사용 이유를 입력하고 신청하면, 인증키가 부여됩니다.

2. C# 날씨 API 연동

  • 프로젝트를 생성합니다.
  • 예보 지점 X, Y 좌표값을 정의합니다.
 public class ForecastPosition
    {
        /// <summary>
        /// 예보지점 X 좌표값
        /// </summary>
        public string XPOS { get; set; }
        /// <summary>
        /// 예보지지점 Y 좌표값
        /// </summary>
        public string YPOS { get; set; }
    }
  • API 문서를 참고하여 응답 전문 클래스를 생성합니다.
namespace Weather
{
    /// <summary>
    /// 기상청 신 동네예보서비스 응답 객체(ROOT)
    /// </summary>
    public class ResponseForecastWebApi
    {
        public ResponseForecastSpaceData response { get; set; }
    }
    /// <summary>
    /// 기상청 신 동네예보서비스 응답 객체(하위)
    /// </summary>
    public class ResponseForecastSpaceData
    {
        public ResposeHeader header { get; set; }
        public ResponseBody body { get; set; }
    }
    /// <summary>
    /// 기상청 신 동네예보서비스 응답 객체(하위)
    /// </summary>
    public class ResposeHeader
    {
        public string resultCode { get; set; }
        public string resultMsg { get; set; }
    }
    /// <summary>
    /// 기상청 신 동네예보서비스 응답 객체(하위)
    /// </summary>
    public class ResponseBody
    {
        public string dataType { get; set; }
        public ForcastItems items { get; set; }
        public string numOfRows { get; set; }
        public string pageNo { get; set; }
        public string totalCount { get; set; }
    }
    /// <summary>
    /// 기상청 신 동네예보서비스 응답 객체(하위)
    /// </summary>
    public class ForcastItems
    {
        public List<ForcastItem> item { get; set; }
    }
    /// <summary>
    /// 기상청 신 동네예보서비스 응답 객체(하위)
    /// </summary>
    public class ForcastItem
    {
        public string baseDate { get; set; }
        public string baseTime { get; set; }
        public string category { get; set; }
        public string fcstDate { get; set; }
        public string fcstTime { get; set; }
        public string fcstValue { get; set; }
        public string nx { get; set; }
        public string ny { get; set; }
    }
}
  • 기상청 API 요청 클래스를 생성합니다.
namespace Weather
{
    /// <summary>
    /// 예보정보 클래스
    /// </summary>
    public class ForecastInfo
    {
        /// <summary>
        /// 서비스 이름(동네예보/초단기실황/초단기예보 등)
        /// </summary>
        string ServiceName { get; set; }
        /// <summary>
        /// 서비스 키
        /// </summary>
        string ServiceKey { get; set; }
        /// <summary>
        /// 예보발표 일자(동네예보일 경우 당일만 조회 가능)
        /// </summary>
        string BaseDate { get; set; }
        /// <summary>
        /// 예보발표 시각
        /// </summary>
        string BaseTime { get; set; }

        public ForecastInfo()
        {
            //우리 동네 날씨 예보
            // ServiceName = "ForecastSpaceData";
            ServiceName = "getVilageFcst";
            //서비스 키(개발계정)
            ServiceKey = 공공포탈에서 발급 받은 키 입력
             BaseDate = DateTime.Now.ToString("yyyyMMdd");
            //현재 BaseTime은 오후 2시로 고정 
            //(BaseTime(발표시간) 14:00 시 fcstTime 18:00 데이터
            BaseTime = "1400";

        }
        /// <summary>
        /// 예보정보를 불러와 저장
        /// </summary>
        public void SetForecastInfo()
        {
            #region 위치 딕셔너리 생성
            //API문서에 격자_위경도 엑셀파일에서 내가 확인하고 싶은 지역의 x,y좌표를 확인하면됨
            Dictionary<string, dynamic> positionInfo = new Dictionary<string, dynamic>();
            //서울 - 서울특별시 역삼동 일대
            positionInfo.Add("서울", new ForecastPosition() { XPOS = "61", YPOS = "125" });
            //경기 - 성남시 분당구 일대
            positionInfo.Add("경기", new ForecastPosition() { XPOS = "62", YPOS = "122" });
            //충청 - 대전광역시 서구 둔산동 일대
            positionInfo.Add("충청", new ForecastPosition() { XPOS = "67", YPOS = "100" });
            //호남 - 광주광역시 서구 치평동 일대
            positionInfo.Add("호남", new ForecastPosition() { XPOS = "58", YPOS = "74" });
            //영남 - 부산광역시 연제구 일대
            positionInfo.Add("영남", new ForecastPosition() { XPOS = "98", YPOS = "76" });
            //강원 - 춘천시 효자동 일대
            positionInfo.Add("강원", new ForecastPosition() { XPOS = "73", YPOS = "134" });
            //제주 - 제주시 아라동 일대
            positionInfo.Add("제주", new ForecastPosition() { XPOS = "53", YPOS = "37" });
            #endregion

            string[] v = new string[positionInfo.Count];
            int i = 0;
            foreach (var info in positionInfo)
            {
                var pos = (ForecastPosition)info.Value;

                v[i] = RequestWeaterInfo(pos.XPOS, pos.YPOS);
                Console.WriteLine($"{info.Key} : {v[i++]}");
            }

            try
            {
               //사용 하는 데이터 베이스에 저장 접속 정보 및 쿼리 작성 하면 됩니다.
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }

        }

        /// <summary>
        /// 해당 예보지역의 예보날씨를 조회
        /// </summary>
        /// <param name="xpos">예보 X좌표</param>
        /// <param name="ypos">예보 Y좌표</param>
        /// <returns>해당 위치의 날씨정보</returns>
        public string RequestWeaterInfo(string xpos, string ypos)
        {
            try
            {
                string returnPty;
                string returnSky;

                RequestHeaderStmt request = new RequestHeaderStmt()
                {
                    RequestUrl = String.Format(@"{0}?ServiceKey={1}&base_date={2}&base_time={3}&nx={4}&ny={5}&numOfRows=10&&dataType=json"
                                    , ServiceName, ServiceKey, BaseDate, BaseTime, xpos, ypos)
                };

                var result = GetStringDominoSvcWebApi(request, false);

                if (result.response.header.resultCode == "00" && result.response.header.resultMsg == "NORMAL_SERVICE")
                {

                    //  API 사용자 활용가이드의 코드값 정보 항목을 확인 하여 필요한 것만 사용

                    // 강수형태 / 하늘상태 추출(코드형태)
                    var pty = result.response.body.items.item.Where(s => s.category == "PTY").ElementAt(0).fcstValue;
                    var sky = result.response.body.items.item.Where(s => s.category == "SKY").ElementAt(0).fcstValue;

                    //추출한 코드 정보를 범주에 맞게 변환
                    if (sky == "1")
                    {
                        returnSky = "맑음";
                    }
                    else if (sky == "3")
                    {
                        returnSky = "구름많음";
                    }
                    else if (sky == "4")
                    {
                        returnSky = "흐림";
                    }
                    else
                    {
                        returnSky = string.Empty;
                    }

                    if (pty == "1")
                    {
                        returnPty = "비";
                    }
                    else if (pty == "2")
                    {
                        returnPty = "비/눈";
                    }
                    else if (pty == "3")
                    {
                        returnPty = "눈";
                    }
                    else if (pty == "4")
                    {
                        returnPty = "소나기";
                    }
                    else
                    {
                        returnPty = string.Empty;
                    }

                    return string.IsNullOrEmpty(returnPty) ? returnSky : $"{returnSky}/{returnPty}";
                }
                else
                {
                    return string.Empty;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return string.Empty;
            }
        }

        /// <summary>
        /// Get방식으로 예보 Web API에 접근하여 JSON 형식으로 예보 데이터를 수신
        /// </summary>
        /// <param name="request"></param>
        /// <param name="isResult"></param>
        /// <returns></returns>
        private ResponseForecastWebApi GetStringDominoSvcWebApi(RequestHeaderStmt request, bool isResult)
        {
            const string CONTENT_TYPE = "application/json; charset=utf-8";
            using (var client = new WebClient())
            {
            
                client.BaseAddress = API 문서에 나와 있는 접속 기본 접속 URL 입력;
                client.Headers.Add(HttpRequestHeader.ContentType, CONTENT_TYPE);
                string resultStr = client.DownloadString(request.RequestUrl);
                Console.WriteLine(resultStr);
                ResponseForecastWebApi respStmt = JsonConvert.DeserializeObject<ResponseForecastWebApi>(resultStr);
                return respStmt;
            }
        }
    }
}
 class Program
    {
        /// <summary>
        /// 메인 메서드
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Console.WriteLine("날씨 정보 확인!!");

            ForecastInfo forecast = new ForecastInfo();
            forecast.SetForecastInfo();

            if (args.Length == 0)
            {
                Console.WriteLine("Press any key to exit.");
                Console.ReadKey();
            }
        }
    }

이상 C#에서 기상청 날씨 API 연동하는 코드였습니다.

 

728x90
반응형

댓글