저는 현재 TypeScript와 React Native로 암호화폐 지갑을 개발하고 있으며, 이번 글에서는 지갑 앱에 업비트의 Public API 를 적용하는 과정에서 경험한 스토리를 써보려 합니다.
다음은 UPbit의 공식 API 문서에서 가져온 업비트에서 거래 가능한 마켓 목록을 가져오는 JavaScript와 Node.js API입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //JavaScript API var data = JSON.stringify(false); var xhr = new XMLHttpRequest(); xhr.withCredentials = true; xhr.addEventListener("readystatechange", function () { if (this.readyState === this.DONE) { console.log(this.responseText); } }); xhr.open("GET", "https://api.upbit.com/v1/market/all"); xhr.send(data); | cs |
1 2 3 4 5 6 7 8 9 10 | // Node.js API var request = require("request"); var options = { method: 'GET', url: 'https://api.upbit.com/v1/market/all' }; request(options, function (error, response, body) { if (error) throw new Error(error); console.log(body); }); | cs |
request 를 보내기 위해 JavaScript API에서는 XMLHttpRequest를 사용했고, Node API에서는 request를 사용한 것을 확인할 수 있습니다.
이 둘의 차이는 무엇일까요?
XMLHttpReuest
오랜 세월 동안 사람들은 XMLHttpRequest (XHR) 를 이용해서 JavaScript 로 비동기 리퀘스트를 처리해왔습니다. 매우 유용했지만, XHR 는 그렇게 좋은 API 는 아니었습니다. 입력, 출력, 그리고 상태(state) 모두를 하나의 객체로 관리해야 했으며, 상태(state) 는 이벤트를 통해 추적해야 했습니다.
다음은 제가 UPbit의 JavaScript API를 제가 개발중인 앱에서 쓸 수 있도록 TypeScript로 변환해서 가져온 코드입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // src/apis/UPbitAPI.ts export const publicUpbitAPI = (method: string, url: string, resolve: Function) => { let data = JSON.stringify(false); const xhr = new XMLHttpRequest(); xhr.withCredentials = true; xhr.addEventListener("readystatechange", function () { if (this.readyState === this.DONE) { // console.log(this.responseText); resolve(this.responseText); } }); xhr.open(method, url); xhr.send(data); } | cs |
뭐가 달라졌는지 보이시나요? API를 publicUpbitAPI 메소드 안에 구현해 놨습니다.
그리고! 매개변수로 method 와 url 말고 resolve라는 Function이 있는 것 보이시나요?!
다음은 다른 파일에서 위의 publicUpbitAPI를 사용하는 코드입니다.
1 2 3 4 5 6 7 8 | // src/stores/tokenStore.ts ... const requestAPI = new Promise((resolve) => { publicUpbitAPI(GET, MARKET_CODE_URL, resolve) }); ... | cs |
여기를 보시면, 매개변수 resolve: Function 의 정체가 나옵니다.
JavaScript UPbit API에서 언뜻 보면 data를 받아와야 할 것 같지만 아닙니다. 제가 원하는 업비트에서 거래 가능한 마켓 목록은 responseText에 있으며, 이를 가져오기 위해 Promise를 만든 것입니다.
물론 이건 제가 꼼수를 좀 부려본 거라, 정석은 아닐 겁니다 하하
여튼, 이렇게 복잡복잡합니다.
request API
그럼 이제 Node API를 보겠습니다. JavaScript API보다 request API 를 사용한 Node API가 훨씬 직관직인 걸 보실 수 있을 겁니다.
하지만, 여전히 안에 들어가서 body를 지지고 볶아서 작업해야하는 건 변함이 없습니다.
그래서 이 request를 요즘의 Promise 기반의 비동기 프로그래밍 방식과 어울리도록 만든 request-promise, fetch, axios 등의 API들이 나왔습니다. 이들은 promise를 반환합니다.
fetch API
다음은 API를 fetch를 변환한 코드입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // src/apis/UPbitAPI.ts const publicUpbitAPI = (method: string, url: string, body: {} = {}) => { return fetch(url, { method: method, //header: {} body: JSON.stringify(body) }).then((response) => response.json()) } } // src/stores/tokenStore.ts @action public loadUpbitTokenList = async () => { await publicUpbitAPI('GET', 'https://api.upbit.com/v1/market/all') .then((responseJson) => this.parseUpbitTokenSymbol(responseJson)) .catch((reject) => { console.error( "Error occurs during requesting TokenList to Upbit :::" + reject ) }) } | cs |
보시는 것처럼 fetch는 promise를 반환합니다. 이를 .then으로 바로 값을 받아올 수 있습니다. 엄청 편하고 직관적입니다.
그럼 다음 포스팅에서는 axios(https://www.npmjs.com/package/axios) 와 fetch(https://www.npmjs.com/package/fetch) 를 비교해보고겠습니다.
참고
https://medium.com/@kkak10/javascript-fetch-api-e26bfeaad9b6