[JS] 공공데이터포털 API 사용하기 : XMLhttp, Fetch, Axios 방법으로 리팩토링하기
2024. 8. 15. 13:20ㆍ개발 회고록 : FrontEnd
2024.08 기준, 공공데이터포탈에서 제공하는 코드 예제
/* Javascript 샘플 코드 */
var xhr = new XMLHttpRequest();
var url = 'http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtNcst'; /*URL*/
var queryParams = '?' + encodeURIComponent('serviceKey') + '='+'서비스키'; /*Service Key*/
queryParams += '&' + encodeURIComponent('pageNo') + '=' + encodeURIComponent('1'); /**/
queryParams += '&' + encodeURIComponent('numOfRows') + '=' + encodeURIComponent('1000'); /**/
queryParams += '&' + encodeURIComponent('dataType') + '=' + encodeURIComponent('XML'); /**/
queryParams += '&' + encodeURIComponent('base_date') + '=' + encodeURIComponent('20210628'); /**/
queryParams += '&' + encodeURIComponent('base_time') + '=' + encodeURIComponent('0600'); /**/
queryParams += '&' + encodeURIComponent('nx') + '=' + encodeURIComponent('55'); /**/
queryParams += '&' + encodeURIComponent('ny') + '=' + encodeURIComponent('127'); /**/
xhr.open('GET', url + queryParams);
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
alert(
'Status: '+this.status
+'nHeaders: '+JSON.stringify(this.getAllResponseHeaders())
+'nBody: '+this.responseText
);
}
};
xhr.send('');
제공된 예제는 복잡하다. XMLhttp은 어느 브라우저에서나 사용가능하지만 코드가 길고 비동기 지원이 되지 않아 콜백지옥이 발생한다.
* 콜백지옥: 함수 안에 함수가 중복되어 코드가 복잡해지는 코드 형태
코드가 복잡해지는 문제는 fetch와 axios로 해결할 수 있다.
* Promise, async-await를 알고 있어야 아래 코드를 이해할 수 있음
그전에 ES6에 맞도록 url의 쿼리스트링 코드를 자바스크립트로 수정해 보자.
1. URI
1.1. 쿼리스트링이란
* 쿼리스트링
인터넷 주소(URI)에서 물음표 뒤에 있는 문자열
* URI
인터넷 주소라는 의미가 'URL'과 상충되어 'Locator'(리소스의 위치) 보다 포괄적인 'Identifier'(리소스 식별자)로 바뀌었다.
* 물음표(?)는 쿼리스트링 시작, 등호(=)는 key-value 선언, 앰퍼샌드(&)는 key-value 연결고리
예시)
www.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=0&ie=utf8&query=맛집
- 쿼리스트링: ?where=nexearch&sm=top_hty&fbm=0&ie=utf8&query=맛집
- key-value: where=nexearch, sm=top_hty, fbm=0&ie=utf8, query=맛집
1.1. URI 쿼리스트링 생성 코드
// 1번
let queryString = '?' + 'serviceKey' + '='+`${serviceKey}`; /*Service Key*/
queryString += '&' + 'pageNo' + '=' + '1';
queryString += '&' + 'numOfRows' + '=' + '1000';
queryString += '&' + 'dataType' + '=' + 'XML';
queryString += '&' + 'base_date' + '=' + '20210628';
queryString += '&' + 'base_time' + '=' + '0600';
queryString += '&' + 'nx' + '=' + '55';
queryString += '&' + 'ny' + '=' + '127';
// 변수명 queryParams를 queryString으로 수정.
// 2번
const SERVICE_KEY = 'Your service key'; /*Service Key*/
const queryParams = {}; // 객체 선언
queryParams['serviceKey'] = SERVICE_KEY;
queryParams['pageNo'] = '1'
queryParams['numOfRows'] = '1000'
queryParams['dataType'] = 'XML'
queryParams['base_date'] = '20210628'
queryParams['base_time'] = '0600'
queryParams['nx'] = '55'
queryParams['ny'] = '127'
let queryString = Object.keys(queryParams).reduce((previous, current) => (
previous + current + '=' + queryParams[current] + '&'
), '?');
queryString = queryString.substring(0, queryString.length - 1); // 마지막 '&' 제거
콘솔로그를 실행하면 1, 2번 쿼리스트링 결과는 서로 똑같다. 쿼리스트링의 조건에 맞춰서 이외 다른 방법으로도 쿼리스트링을 생성할 수 있다.
2. 호출 방법들 (Fetch, Axios)
2.1. API Fetch 적용하는 방법
// fetch
(async () => {
try {
const response = await fetch(url + queryString);
const data = await response.json();
// console.log(data); 확인가능, 즉시실행 함수 밖에서 확인 불가
if (data.response.header.resultCode !== '00') {
// 에러 문구 'Error Code (숫자코드), (오류내용)'
// 해당 OpenAPI 정보 참고자료에서 오류코드 확인가능
throw new Error(
`Code ${data.response.header.resultCode},
${data.response.header.resultMsg}`
);
}
} catch (err) {
console.error('first_api.js', err);
}
})();
// (() => {})(); 즉시함수
// function으로 감싸주어 async function으로 사용 가능
별도 설치 없이 fetch를 불러올 수 있어서 사용성이 좋다. try-catch로 오류를 잡을 수 있지만 http 오류는 별도로 확인해야 한다.
2.2. API Axios 적용하는 방법
// axios
import axios from 'axios'; // npm i axios
(async () => {
try {
const response = await axios.get(url + queryString);
// console.log(response); 확인가능, 즉시실행 함수 밖에서 확인 불가
if (response.header.resultCode !== '00') {
// 에러 문구 'Error Code (숫자코드), (오류내용)'
// 해당 OpenAPI 정보 참고자료에서 오류코드 확인가능
throw new Error(
`Code ${data.response.header.resultCode},
${data.response.header.resultMsg}`
);
}
} catch (err) {
console.error(err);
}
})();
// fetch와 다르게 response.json() 안 해도 response 바로 사용가능
axios는 npm으로 별도 설치해야 사용가능하다. 파일이 무겁지만 http 오류를 try-catch에서 잡을 수 있다.
3. .js 파일 분리
3.1. Fetch 파일 분리하기 - getAPIFetch.js, index.js
// getAPIFetch.js
async function getAPIFetch() {
// URI
const url = 'http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtNcst';
// QueryString
const SERVICE_KEY = 'Your service key'; /*Service Key*/
const queryParams = {}; // 객체 선언
queryParams['serviceKey'] = SERVICE_KEY;
queryParams['pageNo'] = '1'
queryParams['numOfRows'] = '1000'
queryParams['dataType'] = 'XML'
queryParams['base_date'] = '20210628'
queryParams['base_time'] = '0600'
queryParams['nx'] = '55'
queryParams['ny'] = '127'
let queryString = Object.keys(queryParams).reduce((previous, current) => (
previous + current + '=' + queryParams[current] + '&'
), '?');
queryString = queryString.substring(0, queryString.length - 1); // 마지막 '&' 제거
// fetch
try {
const response = await fetch(url + queryString);
const data = await response.json();
if (data.response.header.resultCode !== '00') {
// 에러 문구 'Error Code (숫자코드), (오류내용)'
throw new Error(
`Code ${data.response.header.resultCode},
${data.response.header.resultMsg}`
);
}
return data; // API 응답 반환
} catch (err) {
console.error(err);
}
}
// index.js
import getAPIFetch from './getAPIFetch.js';
getAPIFetch()
.then((response) => {
// response = getAPIFetch()에서 반환되는 값
console.log('Fetch response', response);
})
3.2 Axios 파일 분리하기 - getAPIAxios.js, index.js
// getAPIAxios.js
import axios from 'axios';
async function getAPIAxios() {
// URI
const url = 'http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtNcst';
// QueryString
const SERVICE_KEY = 'Your service key'; /*Service Key*/
const queryParams = {}; // 객체 선언
queryParams['serviceKey'] = SERVICE_KEY;
queryParams['pageNo'] = '1'
queryParams['numOfRows'] = '1000'
queryParams['dataType'] = 'XML'
queryParams['base_date'] = '20210628'
queryParams['base_time'] = '0600'
queryParams['nx'] = '55'
queryParams['ny'] = '127'
let queryString = Object.keys(queryParams).reduce((previous, current) => (
previous + current + '=' + queryParams[current] + '&'
), '?');
queryString = queryString.substring(0, queryString.length - 1); // 마지막 '&' 제거
// axios
try {
const response = await fetch(url + queryString);
if (data.response.header.resultCode !== '00') {
// 에러 문구 'Error Code (숫자코드), (오류내용)'
throw new Error(
`Code ${data.response.header.resultCode},
${data.response.header.resultMsg}`
);
}
return response; // API 응답 반환
} catch (err) {
console.error(err);
}
}
// index.js
import getAPIAxios from './getAPIAxios.js';
getAPIAxios()
.then((response) => {
// response = getAPIAxios()에서 반환되는 값
console.log('Axios response', response);
})
참고자료
기상청_단기예보 ((구)_동네예보) 조회서비스 | 공공데이터포털 (data.go.kr)
URI와 URL, 어떤 차이점이 있나요? | 이랜서 블로그 (elancer.co.kr)
🙂 🙂
'개발 회고록 : FrontEnd' 카테고리의 다른 글
[JS] VPC서버에서 Micro Server 설정과 Node 파일 실행 어떻게 하나요? (0) | 2024.08.20 |
---|---|
VPC서버에서 3세대 Micro Server는 어떻게 생성하나요? (0) | 2024.08.19 |
TMDB API, 제작 프로젝트 문제 해결 (2) (0) | 2024.07.21 |
TMDB API, 제작 프로젝트 문제 해결 (1) (0) | 2024.07.21 |
div 사용을 자제해야 하는 이유 (0) | 2024.02.03 |