National Weather Service(NWS) API는 미국 국립기상청에서 제공하는 무료 공공 데이터 API로, 다양한 날씨 정보를 제공하며, 특히 별도 API 키 없이 사용 가능하므로, 손쉽게 사용할 수 있다. 이번 포스트에서는 Python 기반으로 National Weather Service(NWS) API를 사용하는 방법과 리턴되는 결과를 같이 살펴보도록 하자.
National Weather Service(NWS) API 소개
NWS API는 다양한 날씨 데이터를 제공하는 여러 엔드포인트(Endpoint)를 가지고 있다.
엔드포인트(Endpoint)란?
API 엔드포인트는 API가 서버의 특정 리소스에 대한 요청을 받는 디지털 위치를 말한다.
API에서 엔드포인트는 일반적으로 서버의 리소스 위치를 제공하는 URL(Uniform Resource Locator)을 뜻한다.
각 엔드포인트는 특정한 유형의 날씨 정보에 접근할 수 있도록 설계되어 있다.
- /points: 위치 기반 날씨 데이터
- /gridpoints: 그리드 기반 날씨 데이터
- /alerts: 날씨 경고 및 알림
- /stations: 기상 관측소 데이터
좀 더 자세한 엔드포인트 종류에 대한 설명은 포스트 마지막에 다시 설명하도록 하겠다.
API 키 발급
NWS API는 무료로 사용할 수 있으며, 별도의 API 키가 필요 없어, 손쉽게 사용 가능하다.
API 요청 및 응답 형식
NWS API는 HTTP 요청을 통해 데이터를 제공한다. 응답은 주로 JSON 형식으로 반환된다.
기본 요청 예제
위치 기반 현재 날씨 데이터 가져오기
/point
NWS API는 위치(위도와 경도 혹은 주)를 기반으로 동작한다.
여기서는 미국 텍사스 댈러스(위도: 32.7767 N, 경도: 96.7970 W)의 현재 날씨 데이터를 가져오는 예제를 살펴 보도록 하자.
먼저 엔드포인트 뒤에 위도,경도를 입력하고 requests.get
을 통해 데이터를 요청하고 반환 받는다.
데이터는 JSON 형태로 반환되며, 이 데이터에는 메타 데이터, 식별자, 지리적 좌표, 날씨 정보와 관련된 링크가 포함되어 있다.
다음으로 관측소에 대한 링크 주소를 파싱하고, 그 링크 주소를 통해 현재 날씨 정보를 다시 요청하고, 반환 받아 현재 날씨 정보를 파싱, 정리하여 출력하게 된다.
import requests # 댈러스의 위도와 경도 latitude = 32.7767 longitude = -96.7970 # NWS API 엔드포인트 points_url = f"https://api.weather.gov/points/{latitude},{longitude}" # 위치 정보 가져오기 response = requests.get(points_url) data = response.json() # 관측소 URL 추출 observation_stations_url = data['properties']['observationStations'] # 관측소 데이터 가져오기 stations_response = requests.get(observation_stations_url) stations_data = stations_response.json() stations = stations_data['observationStations'] # 첫 번째 관측소 데이터 가져오기 station_url = stations[0] # 현재 날씨 데이터 가져오기 current_weather_url = f"{station_url}/observations/latest" current_weather_response = requests.get(current_weather_url) current_weather_data = current_weather_response.json() # 현재 날씨 정보 출력 current_observation = current_weather_data['properties'] print("현재 날씨") print(f"온도: {current_observation['temperature']['value']}°C") print(f"습도: {current_observation['relativeHumidity']['value']}%") print(f"바람 속도: {current_observation['windSpeed']['value']} m/s") print(f"풍향: {current_observation['windDirection']['value']}°") print(f"날씨 상태: {current_observation['textDescription']}")
결과 출력
현재 날씨 온도: 32.8°C 습도: 63.641629175669% 바람 속도: 20.52 m/s 풍향: 160° 날씨 상태: Mostly Cloudy
날씨 경고 및 알림 가져오기
날씨 경고 및 알림 예제는 먼저 /point
엔드포인트로 경고 및 알림 URL을 받아 온 뒤, /alerts
엔드포인트로 경고 및 알림 데이터를 받아와 정보를 정리하여 출력한다.
import requests # 오클라호마 시티의 위도와 경도 latitude = 35.4676 longitude = -97.5164 # NWS API 엔드포인트 points_url = f"https://api.weather.gov/points/{latitude},{longitude}" # 위치 정보 가져오기 response = requests.get(points_url) data = response.json() # 경고 및 알림 URL 추출 forecast_zone_url = data['properties']['forecastZone'] # 경고 및 알림 데이터 가져오기 alerts_url = f"https://api.weather.gov/alerts/active?zone={forecast_zone_url.split('/')[-1]}" alerts_response = requests.get(alerts_url) alerts_data = alerts_response.json() # 경고 및 알림 정보 출력 alerts = alerts_data['features'] if alerts: print("현재 날씨 경고 및 알림") for alert in alerts: properties = alert['properties'] print(f"제목: {properties['headline']}") print(f"상태: {properties['event']}") print(f"설명: {properties['description']}") print(f"지시사항: {properties['instruction']}") print("-" * 40) else: print("현재 활성화된 날씨 경고 및 알림이 없습니다.")
결과 출력
현재 날씨 경고 및 알림 제목: Flood Watch issued June 4 at 1:34PM CDT until June 5 at 7:00AM CDT by NWS Norman OK 상태: Flood Watch 설명: * WHAT...Flooding caused by excessive rainfall is possible. * WHERE...Portions of central, east central, southeast, and southern Oklahoma, including the following counties, in central Oklahoma, Cleveland, Grady, Lincoln, McClain, Oklahoma and Pottawatomie. In east central Oklahoma, Pontotoc and Seminole. In southeast Oklahoma, Atoka, Bryan, Coal, Hughes, Johnston and Marshall. In southern Oklahoma, Garvin and Murray. * WHEN...From 7 PM CDT this evening through Wednesday morning. * IMPACTS...Excessive runoff may result in flooding of rivers, creeks, streams, and other low-lying and flood-prone locations. * ADDITIONAL DETAILS... - A complex of storms is expected to bring heavy rain to areas already saturated from previous rains. - http://www.weather.gov/safety/flood 지시사항: You should monitor later forecasts and be alert for possible Flood Warnings. Those living in areas prone to flooding should be prepared to take action should flooding develop. ----------------------------------------
엔드포인트에 대한 자세한 설명
/points
특정 위치(위도 및 경도)의 날씨 정보를 제공한다.
- 예시:
https://api.weather.gov/points/{latitude},{longitude}
- 반환 데이터: 예보 및 그리드 포인트 URL, 관측소 정보 등
/gridpoints
특정 그리드 포인트의 상세 날씨 정보를 제공한다.
- 예시:
https://api.weather.gov/gridpoints/{wfo}/{x},{y}
- 반환 데이터: 특정 그리드 포인트의 날씨 예보 데이터
/alerts
특정 지역의 날씨 경고 및 알림을 제공한다.
- 예시:
https://api.weather.gov/alerts/active?area={state}
- 반환 데이터: 활성화된 날씨 경고 및 알림
/stations
기상 관측소의 데이터를 제공한다.
- 예시:
https://api.weather.gov/stations/{stationId}/observations/latest
- 반환 데이터: 특정 관측소의 최신 관측 데이터
고급 사용 예시
위치 기반 7일 예보 데이터 시각화
댈러스(위도: 32.7767 N, 경도: 96.7970 W)의 7일 예보 데이터를 가져와 시각화하는 예시다.
아래 코드를 활용하여 더 보기 좋은 시각화 결과를 만들어 보자.
import requests import pandas as pd import matplotlib.pyplot as plt # 댈러스의 위도와 경도 latitude = 32.7767 longitude = -96.7970 # NWS API 엔드포인트 points_url = f"https://api.weather.gov/points/{latitude},{longitude}" response = requests.get(points_url) data = response.json() # 예보 URL 추출 forecast_url = data['properties']['forecast'] # 예보 데이터 가져오기 forecast_response = requests.get(forecast_url) forecast_data = forecast_response.json() # 날짜별 최고/최저 온도 데이터 추출 periods = forecast_data['properties']['periods'] dates = [period['startTime'][:10] for period in periods if period['isDaytime']] highs = [period['temperature'] for period in periods if period['isDaytime']] lows = [period['temperature'] for period in periods if not period['isDaytime']] # 화씨에서 섭씨로 변환 highs_c = [(temp - 32) * 5/9 for temp in highs] lows_c = [(temp - 32) * 5/9 for temp in lows] # 데이터프레임 생성 df = pd.DataFrame({ 'Date': dates[:len(lows_c)], 'High (°C)': highs_c[:len(lows_c)], 'Low (°C)': lows_c }) # 데이터 시각화 plt.figure(figsize=(10, 5)) plt.plot(df['Date'], df['High (°C)'], label='High Temp (°C)', marker='o') plt.plot(df['Date'], df['Low (°C)'], label='Low Temp (°C)', marker='o') plt.fill_between(df['Date'], df['High (°C)'], df['Low (°C)'], color='grey', alpha=0.2) plt.xlabel('Date') plt.ylabel('Temperature (°C)') plt.title('7-Day Temperature Forecast for Dallas, TX') plt.xticks(rotation=45) plt.legend() plt.grid(True) plt.tight_layout() plt.show()
결과 출력
오류 처리 및 예외 처리
NWS API를 사용할 때에는 언제든지 다양한 오류가 발생할 수 있으니, 발생할 수 있는 오류를 예외 처리 하는 방법도 같이 알아보자.
import requests import json # 댈러스의 위도와 경도 latitude = 32.7767 longitude = -96.7970 # NWS API 엔드포인트 points_url = f"https://api.weather.gov/points/{latitude},{longitude}" try: # 위치 정보 가져오기 response = requests.get(points_url) response.raise_for_status() data = response.json() # 위치 정보에서 예보 URL 추출 forecast_url = data['properties']['forecast'] # 예보 데이터 가져오기 forecast_response = requests.get(forecast_url) forecast_response.raise_for_status() forecast_data = forecast_response.json() # 현재 날씨 정보 출력 forecast_data_string = json.dumps(forecast_data, indent=4, sort_keys=True) print(forecast_data_string) except requests.exceptions.RequestException as e: print(f"HTTP 요청 오류: {e}") except KeyError as e: print(f"데이터 처리 오류: {e}") except Exception as e: print(f"기타 오류: {e}")
결론
National Weather Service(NWS) 는 API를 사용하여 미국 내 다양한 날씨 데이터를 실시간으로 가져올 수 있으며, 더욱이 무료로 제공되고, API키를 따로 발급받지 않아도 되므로 사용이 간편하다.
또한 National Weather Service(NWS) API는 다양한 엔드포인트를 통해 위치 기반 날씨 정보, 경고 및 알림, 관측소 데이터 등을 제공하고, 간단한 HTTP 요청으로 데이터를 가져올 수 있으며, JSON 형식으로 응답을 반환되므로, 데이터 추가 가공도 손쉽게 처리할 수 있으니 잘 활용해 보자.
예보데이터를 시간별로 받고싶은데 혹시 예시 코드 부탁드려도 되나요ㅜㅜ
아니면 참고 문서 url이라도 부탁드려요..
지금이 오후 1시라면
앞으로 24시간 동안의 예보를 받는 코드를 짜서 1시간에 한번씩 돌려보려 하는데 방법 있을까요
안녕하세요!
질문해 주셔서 감사합니다.
질문 주셨던 내용을 코드로 작성해보다 보니 길어져서 포스트를 하나 발행하였습니다.
아래 링크로 방문 주시면 코드를 확인해 보실 수 있으실꺼에요
24시간 예보 데이터 받는 예제와 함께 1시간마다 실측 데이터를 확인하는 예제를 포함하였습니다.
https://blog.deeplink.kr/?p=3544
질문이 있으시면 또 언제든지 댓글로 남겨주세요. 도움이 되셨기를 바랍니다!
감사합니다.