[BE-03] 기상청 단기예보 계약 검증 + 실패 경로 graceful 정합
작업 내용 (설계 의도)
근거 TDD: ../TDD.md “실패 경로·동시성·멱등”, “Testing Plan”, ADR-002·ADR-003.
변경 사항
weather gateway는 실패 경로가 나머지 둘과 불일치(catch 없음 → 예외 전파)한다. 계약 검증 테스트와 실패 경로 정합을 한 티켓으로 묶는다(같은 impl·같은 테스트 파일을 단일 작업자가 소유해 충돌 방지).
KmaWeatherGatewayImpl.kt(prod)에 facility/geocoding과 동일한try/catchgraceful degradation 추가 —RestClientException/역직렬화 실패/resultCode≠00/빈 items 시 빈Forecast반환 +logger.warn. happy-path·타임아웃(3s/5s) 불변.- fixture
test/resources/fixtures/external/data-go-kr/vilage-fcst.json—response.body.items.item[](category=TMP/SKY/PTY/POP/REH/WSD·fcstDate·fcstTime·fcstValue) 캡처. - 계약 테스트(
infrastructure/weather/gateway/KmaWeatherContractTest.kt) — MockWebServer fixture →WeatherGateway.shortForecast(lat,lng)→ForecastSlot그룹핑/매핑 검증 + 실패 시 빈Forecastdegrade 검증. - live 태그 스펙 —
DATA_GO_KR_SERVICE_KEY존재 시 실 API 호출 무손실 역직렬화 확인, 부재 시 스킵.
롤백: impl 변경은 커밋 revert(런타임 하위 호환, happy-path 불변).
의존
- BE-01 (계약 하네스)
다이어그램
처리 흐름
sequenceDiagram participant T as ContractTest participant M as MockWebServer participant G as KmaWeatherGatewayImpl T->>M: enqueue(vilage-fcst.json) T->>G: shortForecast(lat, lng) G->>M: GET /getVilageFcst M-->>G: fixture (또는 5xx) alt 정상 G-->>T: Forecast(slots) 매핑 검증 else 실패 G-->>T: 빈 Forecast (degrade) end
클래스 의존
flowchart LR CT["KmaWeatherContractTest"] --> ECS["ExternalContractSupport(BE-01)"] CT --> G["KmaWeatherGatewayImpl"] G --> WG["WeatherGateway"] G --> RF["ExternalRestClientFactory"]
테스트 케이스
- fixture의 category별 값이 동일 fcstDate·fcstTime으로 그룹핑돼
ForecastSlot(temperature=TMP, sky=SKY 등)으로 매핑된다(해피). - 슬롯이 date·time 오름차순으로 정렬돼 반환된다(경계).
- 외부 5xx/timeout(
RestClientException) 시 예외를 전파하지 않고 빈Forecast를 반환한다(실패/예외 — 정합 핵심). resultCode≠00또는 빈item[]응답 시 빈Forecast를 반환한다(엣지).- live 스펙:
DATA_GO_KR_SERVICE_KEY부재 시 스킵된다(스킵 경로).