malgleam (맑을림)
기상청 Open API 3종의 타입 안전 Gleam 래퍼. Erlang/JavaScript 양쪽 타겟 지원.
gleam add malgleam@1왜 malgleam인가?
기상청 API를 직접 호출하려면 격자 변환 공식, 카테고리 코드표, 지역번호 목록, XML/JSON 파싱을 모두 직접 처리해야 합니다. malgleam은 이 모든 번거로움을 타입 시스템 뒤에 숨깁니다.
| 직접 호출 시 | malgleam 사용 시 |
|---|---|
| 서울 위경도를 Lambert Conformal Conic 공식으로 격자 변환 | location.seoul |
"T1H", "PTY", "SKY" 코드표 참조 | obs.temperature, obs.precipitation_type |
하늘상태 "1" → 맑음 매핑 | case obs { Clear -> ... } |
중기육상예보 구역코드 "11B00000" 조회 | region.land_seoul_incheon_gyeonggi |
생활기상지수 행정구역코드 "1100000000" 조회 | area.seoul |
| URL 조립 + JSON 파싱 + 에러코드 처리 | 요청 빌더 + 디코더가 전부 처리 |
빠른 시작
서울의 현재 날씨
import malgleam/short_term
import malgleam/location
import gleam/httpc
let request = short_term.ultra_srt_ncst(
service_key: "my-service-key",
location: location.seoul,
base_date: "20240701",
base_time: "0600",
)
let assert Ok(response) = httpc.send(request)
let assert Ok(obs) = short_term.decode_ultra_srt_ncst(response)
obs.temperature // 24.5 (℃)
obs.humidity // 78 (%)
obs.precipitation_type // NoPrecipitation
obs.wind_direction // W (16방위)
obs.wind_speed // 2.1 (m/s)8개 관측 카테고리(T1H, RN1, UUU, VVV, REH, PTY, VEC, WSD)가 의미 있는 필드명의 단일 레코드로 반환됩니다.
위경도로 위치 지정
let busan = location.from_coords(lat: 35.1796, lng: 129.0756)
let request = short_term.vilage_fcst(
service_key: "my-key",
location: busan,
base_date: "20240701",
base_time: "0500",
)Lambert Conformal Conic 격자 변환이 자동으로 처리됩니다.
단기예보 해석
let assert Ok(items) = short_term.decode_vilage_fcst(response)
// 시간별 그룹핑
let groups = short_term.group_by_time(items)
// [#("20240701", "0600", [TMP항목, SKY항목, ...]),
// #("20240701", "0900", [...]), ...]
// 개별 아이템 해석
short_term.parse_sky(sky_item) // Ok(Clear)
short_term.parse_float_value(tmp_item) // Ok(25.0)
short_term.parse_wind_direction(vec_item) // Ok(S)중기예보
import malgleam/mid_term
import malgleam/region
let request = mid_term.mid_land_fcst(
service_key: "my-key",
region: region.land_seoul_incheon_gyeonggi,
forecast_time: "202407010600",
)
let assert Ok(response) = httpc.send(request)
let assert Ok(forecast) = mid_term.decode_mid_land_fcst(response)
// days 4~7은 AM/PM, days 8~10은 하루 단위
list.each(forecast.days, fn(day) {
case day.weather_am {
Some(MidClear) -> "오전 맑음"
Some(MidOvercastWithRain) -> "오전 비"
_ -> "..."
}
})지역 코드를 외울 필요가 없습니다. 잘못된 코드 타입은 컴파일 타임에 차단됩니다.
// OK: mid_land_fcst에 LandRegionId 전달
mid_term.mid_land_fcst(key, region.land_seoul_incheon_gyeonggi, time)
// 컴파일 에러: SeaRegionId는 mid_land_fcst에 전달 불가
mid_term.mid_land_fcst(key, region.sea_west_central, time)생활기상지수
import malgleam/living_index
import malgleam/area
let request = living_index.uv_idx(
service_key: "my-key",
area: area.seoul,
time: "2024070618",
)
let assert Ok(response) = httpc.send(request)
let assert Ok(uv) = living_index.decode_uv_idx(response)
uv.tomorrow // Some(8) — 내일 자외선지수 매우높음시간별 지수 조회:
let assert Ok(freeze) = living_index.decode_freeze_idx(response)
living_index.find_hourly(freeze.hourly, 6) // Some(75) — 6시간 후 동파 위험 높음선택 파라미터는 파이프라인으로
let request = short_term.vilage_fcst(key, location.seoul, "20240701", "0500")
|> short_term.with_rows(100)
|> short_term.with_page(2)지원 엔드포인트 (12개)
단기예보 (malgleam/short_term)
| 함수 | API | 설명 | 반환 타입 |
|---|---|---|---|
ultra_srt_ncst | getUltraSrtNcst | 초단기실황 | Observation |
ultra_srt_fcst | getUltraSrtFcst | 초단기예보 | List(ForecastItem) |
vilage_fcst | getVilageFcst | 단기예보 | List(ForecastItem) |
fcst_version | getFcstVersion | 예보버전 | List(ForecastVersion) |
중기예보 (malgleam/mid_term)
| 함수 | API | 설명 | 반환 타입 |
|---|---|---|---|
mid_fcst | getMidFcst | 중기전망 | MidOutlook |
mid_land_fcst | getMidLandFcst | 중기육상예보 | MidLandForecast |
mid_ta | getMidTa | 중기기온 | MidTempForecast |
mid_sea_fcst | getMidSeaFcst | 중기해상예보 | MidSeaForecast |
생활기상지수 (malgleam/living_index)
| 함수 | API | 설명 | 반환 타입 |
|---|---|---|---|
freeze_idx | getFreezeIdxV2 | 동파가능지수 | FreezeIndex |
uv_idx | getUVIdxV2 | 자외선지수 | UvIndex |
air_diffusion_idx | getAirDiffusionIdxV2 | 대기확산지수 | AirDiffusionIndex |
sen_ta_idx | getSenTaIdxV2 | 체감온도 | SensibleTemperature |
설계 원칙
HTTP 클라이언트 독립
모든 요청 빌더는 gleam/http/request.Request(String)를 반환합니다. HTTP 클라이언트를 자유롭게 선택할 수 있습니다.
-
Erlang:
gleam_httpc -
JavaScript:
gleam_fetch
Result 기반 에러 처리
모든 디코더는 Result(T, ApiError)를 반환합니다.
case short_term.decode_vilage_fcst(response) {
Ok(items) -> // 성공
Error(ApiServiceError(InvalidRequestParameter, msg)) -> // API 에러
Error(JsonDecodeError(msg)) -> // JSON 파싱 실패
Error(UnexpectedResponse(body)) -> // 예상치 못한 응답
}
기상청 API 에러코드(01~99) 전체가 ErrorCode variant로 매핑되어 있습니다.
주요 도시 상수
위치, 지역, 지점 코드를 상수로 제공합니다.
// 단기예보 — 18개 도시 격자좌표
location.seoul location.busan location.daegu location.jeju ...
// 중기예보 — 지점번호, 육상/해상/기온 구역코드
region.seoul_incheon_gyeonggi // StationId
region.land_seoul_incheon_gyeonggi // LandRegionId
region.temp_seoul // TempRegionId
region.sea_west_central // SeaRegionId
// 생활기상지수 — 17개 시도 행정구역코드
area.seoul area.busan area.gyeonggi area.jeju ...Development
gleam build # 빌드
gleam test # 테스트
gleam format # 포맷
gleam docs build # API 문서 생성