axios의 장점과 그 대안

axios가 수년째 업데이트가 없다는 불평을 접하고 axios 대신 fetch를 사용해 볼까 생각했었다. (올해 1월에 접한 이 불평은 정확한 것은 아니었는데 axios는 15일 전인 9월 6일에도 업데이트가 있었다.)

axios가 fetch API에 비해 갖는 핵심 장점은 IE11에서 돌아간다는 것이다. IE11은 fetch API를 지원하지 않는다. 그러나 이 장점은 whatwg-fetch 패키지를 사용하면 해결된다.

timeout 설정, json data를 보낼 때나 받을 때 자동으로 변환, HTTP 인터셉터, 진행상태 추적, 동시 요청 같은 데서 편의성을 제공하지만 fetch API로 불편하게나마 모두 처리할 수 있다. (참고: Axios or fetch(): Which should you use?)

Axios 대신 사용할 수 있는 wretch라는 패키지도 있다. 구형 브라우저에서 Wretch를 사용하려면 fetch polyfill을 이용하면 된다.

myFetch

복잡한 라이브러리를 사용하기 귀찮고 fetch의 장황한 문법도 싫다면 간단한 wrapper 함수를 만들어서 사용하면 된다.

아래 코드를 my-fetch.js 같은 적당한 파일명으로 만들어서 임포트해 사용하면 된다.

export default function (url, body, options) {
    const defaultOptions = {
        method: 'POST',
        cache: 'no-cache',
        headers: {
            'Content-Type': 'application/json'
        }
    };
    options = options || {};
    const unifiedOptions = {...defaultOptions, ...options, ...{ body: JSON.stringify(body) }};
    return fetch(url, unifiedOptions)
        .then(response => {
            if (!response.ok) {
                throw Error(response.status + ' ' + response.statusText);
            }
            return response.json();
        });
}

에러 처리는 “Handling Failed HTTP Responses With fetch()”를 참고했다.

사용법은 아래와 같다. 기본 Request Method는 POST인데 GET으로 바꾸고 싶으면 option에 method를 GET으로 주면 된다.

myFetch('/my/post/end-point', {myData: myData}, options)
    .then(response => response.json())
    .then(data => console.log(data))
    .error(error => console.error(error));

내용물이 fetch니 fetch API를 참고해서 나머지를 코딩하면 된다.

웹팩 같은 번들러를 사용하고 있지 않다면 아래처럼 그냥 함수로 가져와 사용하면 된다.

function myFetch(url, body, options) {
    const defaultOptions = {
        method: 'POST',
        cache: 'no-cache',
        headers: {
            'Content-Type': 'application/json'
        }
    };
    options = options || {};
    const unifiedOptions = {...defaultOptions, ...options, ...{ body: JSON.stringify(body) }};
    return fetch(url, unifiedOptions)
        .then(response => {
            if (!response.ok) {
                throw Error(response.status + ' ' + response.statusText);
            }
            return response.json();
        });
}