728x90
반응형
기상청 API (날씨, 기후 데이터) 완전 정복
개요
기상청에서 제공하는 공공데이터 API는 대한민국의 기상 정보를 실시간으로 제공하는 핵심 서비스입니다. 날씨 앱, 농업 서비스, 관광 플랫폼 등 다양한 분야에서 활용할 수 있는 풍부한 기상 데이터를 제공합니다.
주요 API 서비스 종류
1. 단기예보 조회서비스
- 용도: 3일간의 상세 날씨 예보
- 제공 정보: 기온, 습도, 강수확률, 풍향, 풍속 등
- 갱신 주기: 하루 8회 (02, 05, 08, 11, 14, 17, 20, 23시)
2. 중기예보 조회서비스
- 용도: 4일~10일 후 날씨 전망
- 제공 정보: 날씨 상태, 최고/최저 기온
- 갱신 주기: 하루 2회 (06, 18시)
3. 실시간 관측정보
- 용도: 현재 기상 상황
- 제공 정보: 현재 기온, 습도, 강수량, 바람 정보
- 갱신 주기: 10분마다
4. 특보 조회서비스
- 용도: 기상특보, 태풍정보, 지진정보
- 제공 정보: 특보 발표/해제 상태, 특보 내용
- 갱신 주기: 실시간
5. 생활기상지수
- 용도: 일상생활과 관련된 기상지수
- 제공 정보: 자외선지수, 불쾌지수, 체감온도, 식중독지수 등
- 갱신 주기: 일 1회
API 사용 준비하기
1단계: 서비스 키 발급
- 공공데이터포털 접속
- 회원가입 및 로그인
- "기상청_단기예보 조회서비스" 검색 후 활용신청
- 승인 후 서비스키 확인 (마이페이지 > 개발계정 상세보기)
2단계: 좌표계 이해
기상청 API는 기상청 격자 좌표계를 사용합니다.
- 일반적인 위경도 좌표(WGS84)를 기상청 격자 좌표(X, Y)로 변환 필요
- 또는 기상청에서 제공하는 지역별 격자 좌표표 활용
핵심 API 상세 가이드
단기예보 조회 (가장 많이 사용)
API 엔드포인트:
https://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst
필수 파라미터:
- serviceKey: 발급받은 API 인증키
- numOfRows: 한 페이지 결과 수 (기본값: 10)
- pageNo: 페이지 번호 (기본값: 1)
- dataType: 응답 자료형식 (XML/JSON)
- base_date: 발표일자 (YYYYMMDD 형식)
- base_time: 발표시각 (HHMM 형식)
- nx: 예보지점 X 좌표
- ny: 예보지점 Y 좌표
호출 예시:
const API_KEY = 'your_service_key_here';
const base_date = '20231215';
const base_time = '1100';
const nx = 60; // 서울시 중구 격자 X좌표
const ny = 127; // 서울시 중구 격자 Y좌표
const url = `https://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst?serviceKey=${API_KEY}&numOfRows=1000&pageNo=1&dataType=JSON&base_date=${base_date}&base_time=${base_time}&nx=${nx}&ny=${ny}`;
fetch(url)
.then(response => response.json())
.then(data => {
console.log('날씨 데이터:', data.response.body.items.item);
})
.catch(error => {
console.error('API 호출 오류:', error);
});
응답 데이터 이해하기
기상청 API는 다음과 같은 카테고리 코드로 데이터를 제공합니다:
카테고리 설명 단위
| TMP | 1시간 기온 | ℃ |
| UUU | 풍속(동서성분) | m/s |
| VVV | 풍속(남북성분) | m/s |
| VEC | 풍향 | deg |
| WSD | 풍속 | m/s |
| SKY | 하늘상태 | 코드값 |
| PTY | 강수형태 | 코드값 |
| POP | 강수확률 | % |
| WAV | 파고 | M |
| PCP | 1시간 강수량 | mm |
| REH | 습도 | % |
| SNO | 1시간 신적설 | cm |
하늘상태(SKY) 코드:
- 1: 맑음
- 3: 구름많음
- 4: 흐림
강수형태(PTY) 코드:
- 0: 없음
- 1: 비
- 2: 비/눈
- 3: 눈
- 4: 소나기
실용적인 데이터 파싱 예제
function parseWeatherData(apiResponse) {
const items = apiResponse.response.body.items.item;
const weatherData = {};
// 시간대별로 데이터 그룹핑
items.forEach(item => {
const dateTime = `${item.fcstDate}_${item.fcstTime}`;
if (!weatherData[dateTime]) {
weatherData[dateTime] = {};
}
weatherData[dateTime][item.category] = item.fcstValue;
});
// 사용자 친화적 형태로 변환
const result = Object.keys(weatherData).map(dateTime => {
const data = weatherData[dateTime];
return {
date: dateTime.split('_')[0],
time: dateTime.split('_')[1],
temperature: data.TMP ? `${data.TMP}℃` : null,
humidity: data.REH ? `${data.REH}%` : null,
windSpeed: data.WSD ? `${data.WSD}m/s` : null,
precipitation: data.PCP ? data.PCP : '없음',
precipitationProbability: data.POP ? `${data.POP}%` : null,
skyCondition: getSkyCondition(data.SKY),
precipitationType: getPrecipitationType(data.PTY)
};
});
return result;
}
function getSkyCondition(skyCode) {
const conditions = {
'1': '맑음',
'3': '구름많음',
'4': '흐림'
};
return conditions[skyCode] || '알 수 없음';
}
function getPrecipitationType(ptyCode) {
const types = {
'0': '없음',
'1': '비',
'2': '비/눈',
'3': '눈',
'4': '소나기'
};
return types[ptyCode] || '알 수 없음';
}
좌표 변환 가이드
위경도를 기상청 격자 좌표로 변환
function latLonToGrid(lat, lon) {
const RE = 6371.00877; // 지구 반경(km)
const GRID = 5.0; // 격자 간격(km)
const SLAT1 = 30.0; // 투영 위도1(degree)
const SLAT2 = 60.0; // 투영 위도2(degree)
const OLON = 126.0; // 기준점 경도(degree)
const OLAT = 38.0; // 기준점 위도(degree)
const XO = 43; // 기준점 X좌표(GRID)
const YO = 136; // 기준점 Y좌표(GRID)
const DEGRAD = Math.PI / 180.0;
const re = RE / GRID;
const slat1 = SLAT1 * DEGRAD;
const slat2 = SLAT2 * DEGRAD;
const olon = OLON * DEGRAD;
const olat = OLAT * DEGRAD;
let sn = Math.tan(Math.PI * 0.25 + slat2 * 0.5) / Math.tan(Math.PI * 0.25 + slat1 * 0.5);
sn = Math.log(Math.cos(slat1) / Math.cos(slat2)) / Math.log(sn);
let sf = Math.tan(Math.PI * 0.25 + slat1 * 0.5);
sf = Math.pow(sf, sn) * Math.cos(slat1) / sn;
let ro = Math.tan(Math.PI * 0.25 + olat * 0.5);
ro = re * sf / Math.pow(ro, sn);
let ra = Math.tan(Math.PI * 0.25 + lat * DEGRAD * 0.5);
ra = re * sf / Math.pow(ra, sn);
let theta = lon * DEGRAD - olon;
if (theta > Math.PI) theta -= 2.0 * Math.PI;
if (theta < -Math.PI) theta += 2.0 * Math.PI;
theta *= sn;
const x = Math.floor(ra * Math.sin(theta) + XO + 0.5);
const y = Math.floor(ro - ra * Math.cos(theta) + YO + 0.5);
return { x, y };
}
// 사용 예시
const 서울좌표 = latLonToGrid(37.5665, 126.9780);
console.log(서울좌표); // {x: 60, y: 127}
실제 프로젝트 구현 예제
간단한 날씨 조회 함수
class WeatherAPI {
constructor(serviceKey) {
this.serviceKey = serviceKey;
this.baseUrl = 'https://apis.data.go.kr/1360000/VilageFcstInfoService_2.0';
}
// 현재 시각 기준으로 가장 최신 예보 시각 계산
getLatestForecastTime() {
const now = new Date();
const currentHour = now.getHours();
// 기상청 예보 발표 시간: 02, 05, 08, 11, 14, 17, 20, 23시
const forecastTimes = ['0200', '0500', '0800', '1100', '1400', '1700', '2000', '2300'];
let latestTime = '2300';
let baseDate = now;
for (let i = 0; i < forecastTimes.length; i++) {
const forecastHour = parseInt(forecastTimes[i].substring(0, 2));
if (currentHour >= forecastHour) {
latestTime = forecastTimes[i];
} else {
break;
}
}
// 만약 현재 시간이 02시 이전이면 전날 23시 예보 사용
if (currentHour < 2) {
baseDate.setDate(baseDate.getDate() - 1);
latestTime = '2300';
}
const baseDateStr = baseDate.getFullYear().toString() +
(baseDate.getMonth() + 1).toString().padStart(2, '0') +
baseDate.getDate().toString().padStart(2, '0');
return { base_date: baseDateStr, base_time: latestTime };
}
async getWeather(lat, lon) {
try {
// 위경도를 격자 좌표로 변환
const grid = latLonToGrid(lat, lon);
const { base_date, base_time } = this.getLatestForecastTime();
const url = `${this.baseUrl}/getVilageFcst?` +
`serviceKey=${this.serviceKey}&` +
`numOfRows=1000&pageNo=1&dataType=JSON&` +
`base_date=${base_date}&base_time=${base_time}&` +
`nx=${grid.x}&ny=${grid.y}`;
const response = await fetch(url);
const data = await response.json();
if (data.response.header.resultCode !== '00') {
throw new Error(`API 오류: ${data.response.header.resultMsg}`);
}
return parseWeatherData(data);
} catch (error) {
console.error('날씨 정보 조회 실패:', error);
throw error;
}
}
}
// 사용법
const weatherAPI = new WeatherAPI('your_service_key');
weatherAPI.getWeather(37.5665, 126.9780) // 서울시청 좌표
.then(weather => {
console.log('오늘 날씨:', weather[0]);
})
.catch(error => {
console.error('오류:', error);
});
자주 발생하는 오류와 해결책
1. INVALID_REQUEST_PARAMETER_ERROR
원인: 필수 파라미터 누락 또는 형식 오류 해결:
- base_date, base_time 형식 확인 (YYYYMMDD, HHMM)
- nx, ny 좌표값이 정수인지 확인
2. SERVICE_ACCESS_DENIED_ERROR
원인: 잘못된 서비스키 또는 미승인 상태 해결:
- 공공데이터포털에서 서비스 이용승인 상태 확인
- 서비스키 복사 시 공백 포함 여부 확인
3. SERVICE_TIME_OUT_ERROR
원인: API 서버 응답 지연 해결:
- 재시도 로직 구현
- 요청 간격 조절 (초당 1000건 제한)
고급 활용 팁
1. 캐싱 전략
기상 데이터는 주기적으로 갱신되므로 효율적인 캐싱이 중요합니다.
class WeatherCache {
constructor(ttl = 600000) { // 10분 캐시
this.cache = new Map();
this.ttl = ttl;
}
getKey(lat, lon) {
return `${lat.toFixed(4)}_${lon.toFixed(4)}`;
}
get(lat, lon) {
const key = this.getKey(lat, lon);
const cached = this.cache.get(key);
if (cached && Date.now() - cached.timestamp < this.ttl) {
return cached.data;
}
return null;
}
set(lat, lon, data) {
const key = this.getKey(lat, lon);
this.cache.set(key, {
data: data,
timestamp: Date.now()
});
}
}
2. 여러 지역 동시 조회
async function getMultipleWeather(locations, weatherAPI) {
const promises = locations.map(location =>
weatherAPI.getWeather(location.lat, location.lon)
.then(weather => ({ ...location, weather }))
.catch(error => ({ ...location, error: error.message }))
);
return Promise.all(promises);
}
3. 실시간 알림 시스템
class WeatherAlert {
constructor(weatherAPI) {
this.weatherAPI = weatherAPI;
this.alerts = [];
}
addAlert(lat, lon, condition, callback) {
this.alerts.push({ lat, lon, condition, callback });
}
async checkAlerts() {
for (const alert of this.alerts) {
try {
const weather = await this.weatherAPI.getWeather(alert.lat, alert.lon);
const currentWeather = weather[0];
if (alert.condition(currentWeather)) {
alert.callback(currentWeather);
}
} catch (error) {
console.error('알림 체크 오류:', error);
}
}
}
startMonitoring(interval = 600000) { // 10분마다 체크
setInterval(() => this.checkAlerts(), interval);
}
}
// 사용 예시
const alertSystem = new WeatherAlert(weatherAPI);
// 비가 올 때 알림
alertSystem.addAlert(37.5665, 126.9780,
(weather) => weather.precipitationType !== '없음',
(weather) => console.log('비가 옵니다!', weather)
);
결론
기상청 API는 정확하고 실시간성이 뛰어난 기상 데이터를 제공하는 강력한 도구입니다. 좌표 변환과 데이터 파싱만 잘 이해하면 다양한 날씨 관련 서비스를 구축할 수 있습니다.
다음 글에서는 국토교통부 API를 통한 교통 및 부동산 정보 활용법에 대해 알아보겠습니다!
참고 자료
728x90
반응형
'IT와 과학 > API' 카테고리의 다른 글
| 구글 시트·엑셀 API 자동화 완전 가이드 | 인증·쿼터·오류 대처 + 10분 템플릿 (2025.10월 최신) (0) | 2025.10.04 |
|---|---|
| 국토교통부 API (교통, 부동산 정보) 완전 정복 (1) | 2025.08.08 |
| 🏧 한국 결제 플랫폼 API 완전 분석: 개발자가 알아야 할 모든 것 (3) | 2025.08.08 |
| 한국 주식 API 생태계 완전 가이드 (2025년 12월 최신판) (2) | 2024.10.12 |
| API 테스트 자동화 도구 총정리: 효율적이고 신뢰성 높은 API 테스트 수행법 (2025-08 업데이트) (3) | 2024.10.12 |