React-Native로 날씨 앱을 만들던 도중 openweather의 API를 사용하여 만들려고 했지만, 원하는 정보가 무료버전이라 제대로 제공되지 않는 문제로 해당과정을 어떻게 하면 해결할까 하여 기상청 API를 대신하여 이용하기로 결정
공공 데이터 포털에 접속 → 회원가입, 활용신청
활용신청하는 방법은 간단하니 다음으로 바로 넘어가면
기상청_단기예보 ((구)_동네예보) 조회서비스 를 이용하면 된다.
해당 API 에는 총 4가지의 서비스를 이용할 수 있는데
- 초단기실황조회
- 초단기예보조회
- 단기예보조회
- 예보버전조회
이중에서 초단기 실황조회를 이용하여 현재 온도를 가지고 와보자.
http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtNcst
API 에는 인자로 다음과 같은 값을 가진다.
serviceKey
: 공공데이터포털에서 발급받은 인증키 값이다numOfRows
: 한 페이지 결과 수를 의미한다.(Default: 10)pageNo
: 페이지 번호를 의미한다. (Default: 1)dataType
: 응답받을 데이터 타입을 결정한다. JSON 혹은 XML로 사용해주면 된다 (Default : XML)base_data
: 응답받을 데이터의 발표일자를 넣어준다. (Ex : 20241101)base_time
: 응답받을 데이터의 시간을 넣어준다. (정시단위로 넣어야되고 매시각 10분 이후 호출가능하다)nx
: 예보지점의 X 좌표값ny
: 예보지점의 Y 좌표값
const url = `http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtNcst?serviceKey=${apiKey}&pageNo=${pageNo}&numOfRows=${numOfRows}&dataType=${dataType}&base_date${base_date}&base_time${base_time}&nx=${nx}&ny=${ny}`;
다음과 같이 값에 적절한 값을 넣으면 원하는 날의 데이터 값을 얻을 수 있다.
nx , ny 를 구하는 법
nx, ny는 위도 경도를 의미하는게 아니다. 때문에 값을 변경해줘야되는데 이는 기상청에 상세설명 docx 파일에 작성되어있지만, javascript나 typescript로 작성되어 있지는 않다.
https://gist.github.com/fronteer-kr/14d7f779d52a21ac2f16
위의 사이트의 github 코드를 참고하여 Typscript로 바꿔 사용하였다.
// 기본 상수 정의
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)
// 입력 및 출력 타입 정의
interface LatLng {
lat: number;
lng: number;
}
interface GridXY {
x: number;
y: number;
}
type ConversionCode = 'toXY' | 'toLL';
export function dfsXYConv(code: ConversionCode, v1: number, v2: number): LatLng | GridXY {
const DEGRAD = Math.PI / 180.0;
const RADDEG = 180.0 / Math.PI;
const re = RE / GRID;
const slat1 = SLAT1 * DEGRAD;
const slat2 = SLAT2 * DEGRAD;
const olon = OLON * DEGRAD;
const olat = OLAT * DEGRAD;
const sn = Math.log(Math.cos(slat1) / Math.cos(slat2)) / Math.log(Math.tan(Math.PI * 0.25 + slat2 * 0.5) / Math.tan(Math.PI * 0.25 + slat1 * 0.5));
const sf = (Math.pow(Math.tan(Math.PI * 0.25 + slat1 * 0.5), sn) * Math.cos(slat1)) / sn;
const ro = (re * sf) / Math.pow(Math.tan(Math.PI * 0.25 + olat * 0.5), sn);
let result: LatLng | GridXY;
if (code === 'toXY') {
const ra = (re * sf) / Math.pow(Math.tan(Math.PI * 0.25 + v1 * DEGRAD * 0.5), sn);
let theta = v2 * DEGRAD - olon;
if (theta > Math.PI) theta -= 2.0 * Math.PI;
if (theta < -Math.PI) theta += 2.0 * Math.PI;
theta *= sn;
result = {
x: Math.floor(ra * Math.sin(theta) + XO + 0.5),
y: Math.floor(ro - ra * Math.cos(theta) + YO + 0.5),
};
} else {
// code === "toLL"
const xn = v1 - XO;
const yn = ro - v2 + YO;
const ra = Math.sqrt(xn * xn + yn * yn);
const alat = 2.0 * Math.atan(Math.pow((re * sf) / ra, 1.0 / sn)) - Math.PI * 0.5;
let theta = 0.0;
if (Math.abs(xn) > 0.0) {
theta = Math.atan2(xn, yn);
}
const alon = theta / sn + olon;
result = {
lat: alat * RADDEG,
lng: alon * RADDEG,
};
}
return result;
}
함수 해석
dfsXYConv 함수는 두가지 기능을 가지는데 code가 toXY 는 latitude , longitude 를 받아 nx, ny 값으로 바꿔주고 code 인자가 toLL 일 경우는 nx, ny 값을 latitude, longitude 로 바꿔주는 역할을 해준다.
최종활용
const url = `http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtNcst?serviceKey=${apiKey}&pageNo=${pageNo}&numOfRows=${numOfRows}&dataType=${dataType}&base_date${base_date}&base_time${base_time}&nx=${nx}&ny=${ny}`;
위의 해당 값을 정확히 올바르게 넣어준뒤에 fetch 시켜 결과 값을 받으면
다음과 같이 많은 결과값이 나오는데 여기서 category 에서 ‘T1H’ 부분이 현재 온도를 의미한다.
만약 다른정보를 알고 싶다면 docx 파일 상세 설명에 적혀있다.