달력에 날씨 정보를 보여준다면 좀더 직관적으로 날짜 별 날씨 변화를 인지할 수 있겠다는 생각이 들었다.
이번 내용은 사이드 프로젝트에 공공데이터 포털 API 를 활용하여 달력에 단기 예보 보여주는 작업 진행 중 겪었던 이슈들과 해결 방안 그리고 기상청 데이터를 어떤 방식으로 데이터를 가공했는지 등의 정보를 담고 있다.
공공데이터 포털에서 "날씨" 키워드 조회 시 나온 결과는 예상과 달랐다.
각 API 의 내용을 살펴 본 시간까지 합치면 적지 않은 시간을 허비했다.
휴게소별 날씨정보
원하는 검색 결과를 얻기 위해서는 "예보" 라는 키워드를 사용해야 했다. 그리고 정렬 순서를 "활용순"으로 바꾸면 실제로 많이 사용되는 순서로 예보 정보를 확인할 수 있다.
그 결과 "동네예보" 라고 알려진 기상청단기예보 ((구동네예보) 조회서비스가 가장 적합하게 여겨졌다. 실제로 많은 서비스에서 이 API 를 활용하고 있음을 확인했다.
기상청단기예보 ((구동네예보) 조회서비스 API 는 날씨 정보를 받기 위해 x,y 좌표를 인자로 전달한다.
https://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtNcst?nx=x좌표&ny=y좌표&기타파라미터들추가
그런데 이 x,y 값은 위도, 경도 값이 아니다. API 페이지에서 다운로드 받을 수 있는 doc 문서를 확인해 보니 "Lambert Conformal Conic Projection" 라는 내용이 나온다. 중위도 지방의 한 대륙이나 대양 경도의 크기를 나타내는 일기도를 만드는 데 적당하고 여겨지는 좌표계라고 한다. (출처 : 월간산)
홈페이지에서 다운받을 수 있는 엑셀 문서는 주소별 x,y 좌표값 목록을 제공하고 있고 워드 문서에서는 좌표 변환 코드를 C 언어로만 제공하고 있다. 아쉽게도 JavaScript 코드는 제공하지 않았다. 아직도 많은 곳에서 C 언어가 사용되긴 하지만 좀 더 많은 언어를 제공해주었으면 좋겠다는 아쉬움이 들었다.
다행히 어떤 훌륭한 개발자 분이 변환 코드를 JavaScript 로 만들어 두셔서 바로 가져다 쓸 수 있었다. 그리고 그외 언어에 대한 변환 코드도 댓글로 추가되었다.
이 기상청 단기예보 API 는 다음과 같은 정보를 제공하고 있다.
예보를 위한 두 API (2번, 3번)는 사용 방법이 동일하지만 응답 결과는 2가지 측면에서 다르다.
전달되는 포맷은 동일하나 일부 카테고리의 종류가 다르다.
정렬방식이 다르다.
# getUltraSrtFcst (초단기예보)
- LGT: 낙뢰 kA(킬로암페어)
- T1H: 기온
- PTY: 강수형태 - (초단기) 없음(0), 비(1), 비/눈(2), 눈(3), 빗방울(5), 빗방울눈날림(6), 눈날림(7)
- RN1: 1시간 강수량 mm
- SKY: 단기예보와 동일
- REH: 단기예보와 동일
- UUU: 단기예보와 동일
- VVV: 단기예보와 동일
- VEC: 단기예보와 동일
- WSD: 단기예보와 동일
# getVilageFcst (단기예보)
최대치(1000)로 요청 시 11개의 속성이 시간단위로 3일~4일간의 정보가 전달되기 때문에 600 ~ 900 개의 row 값을 갖는다.
- TMP : 1시간 기온
- UUU: 풍속(동서성분) m/s
- VVV: 풍속(남북성분) m/s
- VEC: 풍향 deg
- WSD: 풍속 m/s
- SKY: 맑음(1), 구름많음(3), 흐림(4)
- PTY: 강수형태 - (단기) 없음(0), 비(1), 비/눈(2), 눈(3), 소나기(4)
- POP: 강수확률 %
- WAV: 파고 M
- PCP: 1시간 강수량 (mm)
- REH: 습도 %
- SNO: 적설량 (cm)
드디어 기상청 날씨 정보를 제공받을 수 있는 방법과 제공되는 데이터 포맷을 이해할 수 있게 되었다.
기상청이나 네이버 날씨 처럼 정확한 세부 날씨 정보를 제공하는 것이 목적이 아니라 여러 날에 걸친 대략 적인 날씨 정보 노출을 목표로 했다. 그래서 내가 제공하는 제공하고자 하는 정보는 다음과 같았다.
그래서 다음 포맷으로 정리해보았다.
interface DayWeather {
date: string; // YYYYMMDD
temperature: { min: number, max: number };
rain: { min: number, max: number };
snow: { min: number, max: number };
sky: number; // 맑음(1), 구름많음(3), 흐림(4) 의 평균값
}
초단기예보는 예보시점부터 6시간 이내의 예보를 알려주고, 여러 날에 걸친 날씨 정보는 단기예보 에서 제공하고 있다.
그리고 내가 제공하려는 정보는 다음과 같이 압축해볼 수 있었다.
문뜩 더 간단하게 사용할 수 있는 방법이 없는지 궁금했다. 하루에 24개로 나뉜 11개의 카테고리 정보를 3~4일 분량으로 전달해주는 정보는 700~900 (24 11 3~4) 개 수준으로 꽤 많았고 굳이 이걸 받아와서 조작하는 과정도 아끼고 싶었기 때문이다.
여러 시간으로 분산된 정보를 어떻게 하나로 통합하지? 혹시 이걸 예보해주는 또 다른 API 가 있는건 아닐까?
현재 날씨와 단기적인 조회를 하고 싶은 상황에서는 적합하지 않다.
결론적으로는 못찾았다.
시간별(24시간)로 11개의 카테고리의 날씨 정보를 어떻게 하나로 압축해서 표현할 것인가?
먼저 날짜 단위로 나눈 후
이렇게 날짜 별로
[
{
"date":"20230124",
"temperature":{"min":-16,"max":-13},
"rain":{"min":0,"max":0},
"snow":{"min":0,"max":0},
"sky":2.2222222222222223}
}
, ...]
위에서 결정된 날씨 변환 포맷 중 하늘(sky) 값의 평균 값에 따라 맑음, 부분흐림, 흐림의 아이콘을 결정했고, 강우(rain), 적설(snow) 의 최저 값이 1보다 크면 비, 눈 혹은 눈비 정보를 표현하고자 했다.
이를 적용할 수 있는 무료 날씨 아이콘도 매우 많았다.
https://peter.build/weather-underground-icons/
- https://github.com/manifestinteractive/weather-underground-icons
- 단순함, 깔끔함
https://bas.dev/work/meteocons
- https://github.com/basmilius/weather-icons
- 애니메이션
난 마지막 것을 선택하여 적용하였다.
결론적으로 다음과 같은 결과물을 얻었다.
오늘까지는 매우 추울 것이고 점차 온오가 올라갈 것임을 한눈에 파악할 수 있다.
그리고 날씨 정보를 이용하기 위해서는 위치 정보 API 특성상 동의가 필요한데... 이것을 항상 활성 시키면 귀찮아질 것 같아 기본적으로는 비활성화 했다.
사용하기 위해서는 필터 정보 중 날씨 필터를 추가하고 위치 정보를 동의한다.(개인정보를 수집하지 않으니 절대 안심)
이번 작업을 통해 공공데이터 포털에서 제공하는 날씨 API 를 사용해보고 날씨 아이콘으로 시각화 해볼 수 있었던 점이 재미있었다. 그리고 달력에서 날씨 정보를 제공함으로써 3~4일간의 예보를 좀더 직관적으로 인지할 수 있는 UI 를 만들어 볼 수 있어 의미있었던 경험이었다.