o2o-site-AEO/docs/WEATHER.md
김성경 1f26bc7065 [feat] solution: 날씨 조건 세분화,
공식채널 단일화, 한일옥 거리 반영
날씨 조건을 7종으로 세분화,
축제 종료 여부와 무관하게 상시 노출,
'지역 읽기'갈래 축소, 야놀자(NOL) 브랜드명 제거.
2026-09-17 17:02:48 +09:00

75 lines
5.3 KiB
Markdown

# 오늘의 날씨
`Open-Meteo → /v1/local/weather → useLiveWeather → WeatherSection`
관측값은 기존 API를 사용하며 브라우저에서 10분마다 갱신한다. 조회 실패 시 마지막 관측값과
관측 시각을 유지한다. 날씨 문구는 API 요청마다 생성하지 않는다. **API 키 없음** — Open-Meteo
는 키 발급 없이 쓰는 무료 공개 엔드포인트다(`services/external/open_meteo.py`).
## Open-Meteo 응답 → 내부 스냅샷
`GET https://api.open-meteo.com/v1/forecast?latitude=&longitude=&current=temperature_2m,weather_code,wind_speed_10m&timezone=auto`
원본 `current` 블록(`temperature_2m`·`weather_code`·`wind_speed_10m`·`time`)을 어댑터가
`{temperature, weather_code, wind_speed, observed_at, timezone, latitude, longitude}`
정규화한다(`open_meteo.py:fetch_current_weather`). `weather_code`는 WMO 표준 정수 코드 그대로
저장·전달되고, 하늘 상태 문구로 바꾸는 건 아래 두 곳뿐이다 — **반드시 같은 구간이어야 한다**
(하이드레이션 전엔 백엔드 값, 후엔 브라우저 값을 쓰는데 표가 다르면 같은 날씨인데 문구가 바뀐다):
- 서버: `site_payload._weather_condition()` — 프리렌더 스냅샷에 쓰인다.
- 브라우저: `use-live-weather.ts:condition()` — 10분마다 재조회할 때 쓰인다.
| 코드 | 날씨 상태(한국어) | 날씨 상태(영어) | 내부 분류 |
|---|---|---|---|
| 0 | 맑음 | Clear sky | 맑음 |
| 1 | 대체로 맑음 | Mainly clear | 구름많음 |
| 2 | 구름 조금 | Partly cloudy | 구름많음 |
| 3 | 흐림 | Overcast | 구름많음 |
| 45 | 안개 | Fog | 안개 |
| 48 | 착빙성 안개 (서리 안개) | Depositing rime fog | 안개 |
| 51 | 가벼운 이슬비 | Drizzle: Light intensity | 이슬비 |
| 53 | 보통 이슬비 | Drizzle: Moderate intensity | 이슬비 |
| 55 | 강한 이슬비 | Drizzle: Dense intensity | 이슬비 |
| 56 | 가벼운 착빙성 이슬비 | Freezing Drizzle: Light intensity | 어는비 |
| 57 | 강한 착빙성 이슬비 | Freezing Drizzle: Dense intensity | 어는비 |
| 61 | 약한 비 | Rain: Slight intensity | 비 |
| 63 | 보통 비 | Rain: Moderate intensity | 비 |
| 65 | 강한 비 | Rain: Heavy intensity | 강한비 |
| 66 | 약한 착빙성 비 (얼어붙는 비) | Freezing Rain: Light intensity | 어는비 |
| 67 | 강한 착빙성 비 | Freezing Rain: Heavy intensity | 어는비 |
| 71 | 약한 눈 | Snow fall: Slight intensity | 눈 |
| 73 | 보통 눈 | Snow fall: Moderate intensity | 눈 |
| 75 | 강한 눈 | Snow fall: Heavy intensity | 눈 |
| 77 | 싸라기눈 (진눈깨비) | Snow grains | 눈 |
| 80 | 약한 소나기 | Rain showers: Slight | 소나기 |
| 81 | 보통 소나기 | Rain showers: Moderate | 소나기 |
| 82 | 강한 소나기 | Rain showers: Violent | 소나기 |
| 85 | 약한 소나기성 눈 | Snow showers: Slight | 소나기 |
| 86 | 강한 소나기성 눈 | Snow showers: Heavy | 소나기 |
| 95 | 뇌우 (천둥번개) | Thunderstorm: Slight or moderate | 뇌우 |
| 96 | 우박을 동반한 약한 뇌우 | Thunderstorm with slight hail | 뇌우 |
| 99 | 우박을 동반한 강한 뇌우 | Thunderstorm with heavy hail | 뇌우 |
이 27개가 Open-Meteo `weather_code`의 전체 정의 값이다 — 표에 없는 값(파싱 실패 포함)만
안전하게 `흐림`으로 떨어진다(실제로는 도달하지 않는 방어 분기).
`weatherMood()`(`derive.ts`)는 위 11종을 화면 배경 그림용으로 다시 4종(맑음/흐림/비/눈)으로
뭉친다 — 정규식 기반이라 새 분류를 추가해도 대개 자동으로 걸린다(예: "이슬비"·"강한비"·"어는비"는
모두 `/비|우/` 패턴에 "비"가 들어 있어 `비`로 걸린다). `WeatherSection``skyKey`는 노트가
실제로 있는 세부 조건(구름많음/안개/소나기/뇌우/이슬비/강한비/어는비)이면 그 조건 그대로 쓰고,
그 외(맑음/흐림/비/눈)엔 `mood`로 내려간다 — 어차피 세부 조건과 mood 값이 같기 때문이다.
`weather_notes.json → weather_notes.py → site_payload._weather → noteSets/tempNoteSets`
하늘 11종(맑음·구름많음·안개·비·이슬비·강한비·어는비·눈·소나기·뇌우·흐림)·기온 5구간에 각
5문구를 싣는다. 첫 렌더는 첫 문장으로 고정해 하이드레이션을 맞추고, 브라우저에서는 무작위 시작
후 20초마다 한 바퀴 안에서 중복 없이 순환한다. 기온 구간은 기존 `weatherBand`의 30·25·20·10도다.
구름많음·안개·소나기·뇌우·이슬비·강한비·어는비는 그림(mood)상 흐림 또는 비와 같이 묶이지만
문구는 조건별로 따로 쓴다. **비 중에서도 어는비(착빙성)만 안전 안내가 다르다** — 도로·보행
결빙 위험을 짚는 문구가 필요해서 이슬비·강한비와 갈랐다(2026-09-17).
목업 README 2.3의 순환 계약을 제품으로 옮겼다. 군산 전용 시설·장소를 다른 사업장에 복사하지
않도록 기본 문구는 장소·시설·영업시간을 주장하지 않는 공통 안내로 구성한다. **LLM 생성이 아니다.**
지역별 장소 추천을 자동 생성하는 작업은 포함하지 않았다. 목업의 수기 문구·산출물은 변경하지 않는다.
옛 단일 `note`·`notes`·`tempNotes` payload도 계속 지원한다. 이미 발행된 사이트는 재발행해야 반영된다.