JS

Axios 와 Fetch

728x90

이 내용은 아래의 주소를 참조하여 작성되었습니다.

(https://blog.logrocket.com/axios-or-fetch-api/)

 

Axios 와 Fetch 둘 다, 서버와 클라이언트간 비동기 통신을 위해서 사용되는 javascript 라이브러리다.

 

 

* AJAX ?

AJAX 란 Asynchronous Javascript And XML 의 약자로, JS 를 이용해서 클라이언트 서버 간 XML 데이터를 비동기적으로 주고 받게 해주며, XMLHttpRequest 객체를 이용해서 전체 페이지를 reload 하는게 아니라, 필요한 데이터 일부분만 reload 하는 방식이다.

 

Axios 와 Fetch 는 AJAX 를 구현한 JS 라이브러리로, 둘의 차이점을 살펴보면..

 

 

 -1) 호환성 문제

Axios 의 경우 브라우져가 구버젼이든 신버젼이든 상관없이 사용이 가능하다

그러나 Fetch 의 경우 지원하지 않는 브라우져의 버젼이 있으며, 맞지 않는 버젼과 호환시키려면

polyfill 을 사용해서 호환성을 맞춰야 한다.

 

* fetch 로 호환 가능한 브라우저 목록

아래 링크에 더 많은 리스트가 적힘

 

(fetch 가 호환 가능한 버젼 종류)

https://caniuse.com/#search=Fetch

 

Can I use... Support tables for HTML5, CSS3, etc

About "Can I use" provides up-to-date browser support tables for support of front-end web technologies on desktop and mobile web browsers. The site was built and is maintained by Alexis Deveria, with occasional updates provided by the web development commu

caniuse.com

 

(fetch 로 호환을 맞추는 방법 서술)

https://github.com/github/fetch

 

github/fetch

A window.fetch JavaScript polyfill. Contribute to github/fetch development by creating an account on GitHub.

github.com

 

-2) Response Timeout

Axios 의 경우 Timeout 을 넣어줄 때, Axios 에 옵션값으로 넣어 줄 수가 있으나, 

Fetch 의 경우 AbortController 라는 interface 를 활용해서 구현해야 한다.

 

아래는 두 차이점을 코드로 보인 것 이다.

axios({
  method: 'post',
  url: '/login',
  timeout: 4000,    
  data: {
    firstName: 'dy',
    lastName: 's'
  }
})
.then(response => {/* handle the response */})
.catch(error => console.error('timeout exceeded'))
cs

 

 

const controller = new AbortController();
const options = {
  method: 'POST',
  signal: controller.signal,
  body: JSON.stringify({
    firstName: 'dy',
    lastName: 's'
  })
};  
const promise = fetch('/login', options);
const timeoutId = setTimeout(() => controller.abort(), 4000);
 
promise
  .then(response => {/* handle the response */})
  .catch(error => console.error('timeout exceeded'));
cs

 

 

 

AbortController 에 대한 자세한 설명은 아래 참조

https://developer.mozilla.org/ko/docs/Web/API/AbortController

 

AbortController

AbortController 인터페이스는 하나 이상의 웹 요청을 취소할 수 있게 해준다.

developer.mozilla.org

 

 

-3) 자동 JSON 형 변환

Axios 의 경우 별도의 형 변환 없이 JSON 타입의 데이터로 알아서 stringify 해주지만, (Axios 의 경우 자동으로 stringify 되는 부분을 오버라이딩을 사용해서 개발자가 원하는 타입으로 변환이 가능하다)

fetch 의 경우 직접 JSON 형태로 변환시켜야한다.

// axios
axios.get('https://api.github.com/orgs/axios')
  .then(response => {
    console.log(response.data);
  }, error => {
    console.log(error);
  });
 
// fetch()
fetch('https://api.github.com/orgs/axios')
  .then(response => response.json())    
  .then(data => {
    console.log(data) 
  })
  .catch(error => console.error(error));
cs

 

 

-4) HTTP Interceptor

Axios 의 특징 중 하나는 HTTP Request 에 대한 intercept 가 가능하다는 점이다. 이 특징은 클라이언트가 서버로 request 를 보낼때, 보낸 내용이 어떻게 되었는지 확인하기 위한 logging 작업과 authentication(인증) 작업을 거쳤을때, http request 에 변화를 주기 위해서 사용되기도 한다.

아래는 axios 를 이용한 intercept 예시이다.

axios.interceptors.request.use(config => {
  // log a message before any HTTP request is sent
  console.log('Request was sent');
 
  return config;
});
 
// sent a GET request
axios.get('https://api.github.com/users/sideshowbarker')
  .then(response => {
    console.log(response.data);
  });
cs

 

 

-5) Download Progress

리소스를 받아오는 속도는 웹 성능에 있어서 주요한 지표중 하나인데, 

유저마다 인터넷 속도가 다르고, 큰 리소스를 받아오는 경우, 일부 유저들에겐 느린 속도로 리소스를 받기 때문에

성능 하락의 주요 원인이 된다.

그래서 과거에는 XMLHttpRequest.onprogress 를 사용해서 그 점을 보완했다고 한다

 

fetch 의 경우 onprogress handler 를 제공하지 않으며, 대신에 ReadableStream 이란 것을 제공한다.

아래는 ReadableStream 을 이용한 예제 코드이다.

// original code: https://github.com/AnthumChris/fetch-progress-indicators
 
<div id="progress" src="">progress</div>
<img id="img">
 
<script>
 
'use strict'
 
const element = document.getElementById('progress');
 
fetch('https://fetch-progress.anthum.com/30kbps/images/sunrise-baseline.jpg')
  .then(response => {
 
    if (!response.ok) {
      throw Error(response.status+' '+response.statusText)
    }
 
    // ensure ReadableStream is supported
    if (!response.body) {
      throw Error('ReadableStream not yet supported in this browser.')
    }
 
    // store the size of the entity-body, in bytes
    const contentLength = response.headers.get('content-length');
 
    // ensure contentLength is available
    if (!contentLength) {
      throw Error('Content-Length response header unavailable');
    }
 
    // parse the integer into a base-10 number
    const total = parseInt(contentLength, 10);
 
    let loaded = 0;
 
    return new Response(
 
      // create and return a readable stream
      new ReadableStream({
        start(controller) {
          const reader = response.body.getReader();
 
          read();
          function read() {
            reader.read().then(({done, value}) => {
              if (done) {
                controller.close();
                return
              }
              loaded += value.byteLength;
              progress({loaded, total})
              controller.enqueue(value);
              read();
            }).catch(error => {
              console.error(error);
              controller.error(error)                  
            })
          }
        }
      })
    );
  })
  .then(response => 
    // construct a blob from the data
    response.blob()
  )
  .then(data => {
    // insert the downloaded image into the page
    document.getElementById('img').src = URL.createObjectURL(data);
  })
  .catch(error => {
    console.error(error);
  })
 
function progress({loaded, total}) {
  element.innerHTML = Math.round(loaded/total*100)+'%';
}
 
</script>
cs

 

 

Axios 의 경우 이보다 더 간편하며,

특이한 것 중 하나가 

Axios Progress Bar 모듈이 존재하며, 이를 활용하면 진행 속도도 볼 수 있을 뿐 아니라, 

코드를 더 간략화 할 수 있다.

 

* Axios Progress Bar

https://github.com/rikmms/progress-bar-4-axios/

 

rikmms/progress-bar-4-axios

Slim progress bar (NProgress) for Web applications that use Axios library for HTTP requests - rikmms/progress-bar-4-axios

github.com

 

<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/rikmms/progress-bar-4-axios/0a3acf92/dist/nprogress.css" />
 
<script src="https://cdn.rawgit.com/rikmms/progress-bar-4-axios/0a3acf92/dist/index.js"></script>
cs

 

먼저 위와 같은 html 코드로 모듈을 가져온뒤,

 

아래 같은 코드 예시로 활용할 수 있다.

<img id="img">
 
<script>
 
loadProgressBar();
 
const url = 'https://fetch-progress.anthum.com/30kbps/images/sunrise-baseline.jpg';
 
function downloadFile(url) {
  axios.get(url, {responseType: 'blob'})
    .then(response => {
      const reader = new window.FileReader();
      reader.readAsDataURL(response.data); 
      reader.onload = () => {
        document.getElementById('img').setAttribute('src', reader.result);
      }
    })
    .catch(error => {
      console.log(error)
    });
}
 
downloadFile(url);
 
</script>
cs

 

 

-6) Simultaneous Requests

동시에 여러 요청 (requests) 를 보내고자 하는 경우,

axios 는 axios.all() 이란 method 를 활용해서 requests 들을 array 형태로 보내며,

axios.spread() method 를 이용해서, 각 요청에 따른 response 를 받아온다.

아래는 관련 코드 예제이다.

axios.all([
  axios.get('https://api.github.com/users/iliakan'), 
  axios.get('https://api.github.com/users/taylorotwell')
])
.then(axios.spread((obj1, obj2) => {
  // Both requests are now complete
  console.log(obj1.data.login + ' has ' + obj1.data.public_repos + ' public repos on GitHub');
  console.log(obj2.data.login + ' has ' + obj2.data.public_repos + ' public repos on GitHub');
}));
cs

 

 

 

fetch 의 경우 JS 내장 함수인 Promise.all() 을 활용하면, 이 기능이 구현 가능하다

아래는 코드 예제이다.

Promise.all([
  fetch('https://api.github.com/users/iliakan'),
  fetch('https://api.github.com/users/taylorotwell')
])
.then(async([res1, res2]) => {
  const a = await res1.json();
  const b = await res2.json();
  console.log(a.login + ' has ' + a.public_repos + ' public repos on GitHub');
  console.log(b.login + ' has ' + b.public_repos + ' public repos on GitHub');
})
.catch(error => {
  console.log(error);
});
cs

 

 

 

정리하면,

Axios 의 경우 더 간략화된 코드를 제공하고, 사용하기엔 간편하다,

하지만, fetch 라고 해서 axios 의 기능을 구현을 못하는 것은 아니고, native API 를 쓰는 것을 선호하는 경우, fetch 를 사용하는 것이 더 나을 수도 있다. 

결국은 사용자가 어떤 부분에 있어서 더 편한지에 따라 사용하면 될 것 같다.

728x90