💻 Frontend

Axios

category
💻 Frontend

Axios

브라우저와 node.js에서 사용할 수 있는 Promise 기반 HTTP 클라이언트 라이브러리

특징

  • 브라우저를 위해 XMLHttpRequests 생성
  • node.js를 위해 http 요청 생성
  • Promise API 지원
  • 요청 및 응답 인터셉트
  • 요청 및 응답 데이터 변환
  • 요청 취소
  • JSON 데이터 자동 변환
  • XSRF를 막기위한 클라이언트 사이드 지원
 

설치

axios는 라이브러리 이기 때문에 별도의 설치 명령어를 입력해야 합니다:
$ yarn add axios $ npm install axios
 

Axios API

axios에 해당 config를 전송하면 요청이 가능합니다.

axios(config)

// POST 요청 전송 axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone' } });
 

axios(url[,config])

// GET 요청 전송 (기본값) axios('/user/12345');
 
요청 메소드 명령어
모든 요청 메소드의 명령어를 제공합니다.
  • axios.request(config)
  • axios.get(url[, config])
  • axios.delete(url[, config])
  • axios.head(url[, config])
  • axios.options(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])
  • axios.patch(url[, data[, config]])
명령어 메소드를 사용시 'url', 'method', 'data' 속성을 config에서 지정할 필요가 없습니다.
// POST 요청 전송 axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone' } });
// POST 요청 전송 axios.post('/user/12345', { firstName: 'Fred', lastName: 'Flintstone' })
 
 

Axios 인스턴스

custom config로 새로운 Axios 인스턴스를 생성할 수 있습니다.

axios.create([config])

const instance = axios.create({ baseURL: 'https://some-domain.com/api/', timeout: 1000, headers: {'X-Custom-Header': 'foobar'} });
 

요청 config

다음은 요청을 만드는 데 사용할 수 있는 config 옵션들입니다.

url

url은 요청을 보내는 서버 URL 입니다. 옵션들 중 url만 필수입니다.
axios({ url: '/user' })
 

method

method는 요청을 생성할 때 사용되는 메소드입니다. 기본값은 get입니다.
  • get
  • post
  • delete
  • patch
  • put …
axios({ method: 'get' })
 

baseURL

url이 절대값이 아닌 경우 URL 앞에 baseURL이 붙습니다.
상대적인 URL을 전달하려고 하거나, 중복적인 URL을 없애려고 하려면 해당 option을 설정하는 것이 좋습니다.
axios({ baseURL: 'https://some-domain.com/api' })
 

transformRequest

transformRequest는 요청 데이터를 서버로 전송하기 전에 변경할 수 있게 해줍니다.
put, post, patch, delete 메소드에서만 적용됩니다.
또한 추가적으로 헤더 객체를 수정할 수 있습니다.
transformRequest: [function (data, headers) { // 데이터를 변환하려는 작업 수행 return data; }],
 

transformResponse

transformResponse는 응답 데이터가 then/catch로 전달되기 전에 변경할 수 있게 해줍니다.
transformResponse: [function (data) { // 데이터를 변환하려는 작업 수행 return data; }],
 

headers

headers는 사용자 지정 헤더입니다.
headers: {'X-Requested-With': 'XMLHttpRequest'},
 

params

params은 요청과 함께 전송되는 URL 파라미터입니다. 일반 객체나 URLSearchParams 객체여야 합니다.
참고: null이나 undefined는 URL에 렌더링되지 않습니다.
params: { ID: 12345 },
 
 
 
 
 
 
 
 
 
 

응답 스키마

요청에 대한 응답은 다음과 같은 정보를 가지고 있습니다.
{ // `data`는 서버가 제공하는 응답입니다. data: {}, // `status`는 HTTP 상태 코드입니다. status: 200, // `statusText`는 HTTP 상태 메시지입니다. statusText: 'OK', // `headers`는 HTTP 헤더입니다. // 모든 헤더 이름은 소문자이며, 괄호 표기법을 사용하여 접근할 수 있습니다. // 예시: `response.headers['content-type']` headers: {}, // `config`는 요청을 위해 `Axios`가 제공하는 구성입니다. config: {}, // `request`는 이번 응답으로 생성된 요청입니다. // 이것은 node.js에서 마지막 ClientRequest 인스턴스 입니다. // 브라우저에서는 XMLHttpRequest입니다. request: {} }
 

Config 기본값

모든 요청에 적용될 config 기본값을 지정할 수 있습니다.

전역 Axios 기본값

axios.defaults.baseURL = 'https://api.example.com'; axios.defaults.headers.common['Authorization'] = AUTH_TOKEN; axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
 

커스텀 인스턴스 기본값

// 인스턴스를 생성할때 config 기본값 설정하기 const instance = axios.create({ baseURL: 'https://api.example.com' }); // 인스턴스를 만든 후 기본값 변경하기 instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
 

Config 우선 순위

Config는 우선 순위에 따라 병합됩니다. 라이브러리에서의 기본값, 인스턴스의 defaults 속성, 요청의 config 인자를 순서대로 찾습니다. 다음은 예제입니다.
우선순위
  1. instance config 인자
  1. 인스턴스 defaults
  1. axios 자체 기본 값
// 라이브러리에서 제공하는 config 기본값을 사용하여 인스턴스 만들기 // 이 때 timeout 값은 라이브러리의 기본값인 '0'입니다. const instance = axios.create(); // 라이브러리에 대한 timeout 값 재정의 // 이제 모든 요청은 시간 초과 전 2.5초 대기하는 인스턴스를 사용합니다. instance.defaults.timeout = 2500; // 시간이 오래 걸리는 요청에 대한 timeout 값 재정의 instance.get('/longRequest', { timeout: 5000 });
 

인터셉터(interceptor)

then 또는 catch로 처리되기 전에 요청과 응답을 가로챌수 있습니다.
// 요청 인터셉터 추가하기 -> 요청 전 수행 axios.interceptors.request.use(function (config) { // 요청이 전달되기 전에 작업 수행 return config; }, function (error) { // 요청 오류가 있는 작업 수행 return Promise.reject(error); }); // 응답 인터셉터 추가하기 -> 응답 후 수정 axios.interceptors.response.use(function (response) { // 2xx 범위에 있는 상태 코드는 이 함수를 트리거 합니다. // 응답 데이터가 있는 작업 수행 return response; }, function (error) { // 2xx 외의 범위에 있는 상태 코드는 이 함수를 트리거 합니다. // 응답 오류가 있는 작업 수행 return Promise.reject(error); });
나중에 필요할때 인터셉터를 제거할 수 있습니다.
const myInterceptor = axios.interceptors.request.use(function () {/*...*/}); axios.interceptors.request.eject(myInterceptor);
커스텀 인스턴스에서도 인터셉터를 추가할 수 있습니다.
const instance = axios.create(); instance.interceptors.request.use(function () {/*...*/});
 

요청 취소

calcelToken을 이용해 요청을 취소할 수 있습니다.
아래와 같이 CancelToken.source 팩토리를 사용하여 cancel 토큰을 만들수 있습니다:
const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios.get('/user/12345', { cancelToken: source.token }).catch(function (thrown) { if (axios.isCancel(thrown)) { console.log('Request canceled', thrown.message); } else { // 에러 핸들링 } }); axios.post('/user/12345', { name: 'new name' }, { cancelToken: source.token }) // 요청 취소하기 (메시지 파라미터는 옵션입니다) source.cancel('Operation canceled by the user.');
실행자 함수를 CancelToken 생성자에 전달하여, 취소 토큰을 만들수도 있습니다:
const CancelToken = axios.CancelToken; let cancel; axios.get('/user/12345', { cancelToken: new CancelToken(function executor(c) { // 실행자 함수는 취소 함수를 파라미터로 받습니다. cancel = c; }) }); // 요청 취소하기 cancel();
 

Axios vs Fetch

문법

문법적으로는 fetch나 axios 크게 다를게 없습니다.
fetch(url); axios(url)
fetch(url, { method: "GET", // 다른 옵션도 가능합니다 (POST, PUT, DELETE, etc.) headers: { "Content-Type": "application/json", }, body: JSON.stringify({}), }); axios(url, { method: "get", // 다른 옵션도 가능합니다 (post, put, delete, etc.) headers: {}, data: {}, });
크게 다른 점은 axios는 더 다양한 방법으로 요청할 수 있다는 것입니다.
axios({ method: "get", url: url, headers: {}, data: {}, }); axios.get(url, { // 설정 옵션 });
 

JSON 변환

axios와 fetch의 가장 큰 다른 점은 JSON변환이라고 생각합니다.
const url = "https://jsonplaceholder.typicode.com/todos"; fetch(url) .then((response) => response.json()) .then((data)=> console.log(data));
fetch()는 .then() 메서드에서 처리된 promise를 반환합니다. 이 때는 아직 우리가 필요한 JSON 데이터의 포맷이 아니기 때문에 응답 객체의 .json() 메서드를 호출합니다. 그러면 JSON 형식의 데이터로 이행(resolve)된 또 다른 promise를 반환합니다. 따라서 일반적인 fetch 요청은 두 개의 .then() 호출을 갖습니다.
 
다음은 같은 요청을 Axios로 수행하는 코드입니다.
const url = "https://jsonplaceholder.typicode.com/todos"; axios.get(url).then((response) => console.log(response.data));
Axios를 사용하면 응답 데이터를 기본적으로 JSON 타입으로 사용할 수 있습니다. 응답 데이터는 언제나 응답 객체의 data 프로퍼티에서 사용할 수 있습니다.
다음과 같이 설정 옵션을 통해 responseType을 지정하여 기본 JSON 데이터 타입을 재정의 할 수도 있습니다.
axios.get(url, { responseType: "json", // options: 'arraybuffer', 'document', 'blob', 'text', 'stream' });
 

문자열 변환

이를 위해서는 데이터를 JSON 문자열로 직렬화해야 합니다. POST 메서드로 JavaScript 객체를 API로 전송하면 Axios가 자동으로 데이터를 문자열로 변환해줍니다.
다음은 Axios를 사용해 post 요청을 수행하는 코드입니다.
const url = "https://jsonplaceholder.typicode.com/todos"; const todo = { title: "A new todo", completed: false, }; axios .post(url, { headers: { "Content-Type": "application/json", }, data: todo, }) .then(console.log);
Axios로 post요청을 할 때 요청 본문(request body)으로 보내고자 하는 data는 data 프로퍼티에 할당합니다. 컨텐츠 유형 헤더도 설정할 수 있습니다. 기본적으로 axios는 Content-Type을 application/json으로 설정합니다.
 
axios와 다르게 fetch API를 사용한다면 JSON.stringify()를 사용하여 객체를 문자열으로 변환한 뒤 body에 할당해야 합니다.
const url = "https://jsonplaceholder.typicode.com/todos"; const todo = { title: "A new todo", completed: false, }; fetch(url, { method: "post", headers: { "Content-Type": "application/json", }, body: JSON.stringify(todo), }) .then((response) => response.json()) .then((data) => console.log(data));
또한 fetch를 사용하면 명시적으로 Content-Type을 application/json으로 설정해야 합니다.
 

성능

fetch와 axios 모두 promise 기반이기 때문에 성능 문제를 일으키지 않을 것입니다.
notion image
위 그래프에서 확인할 수 있듯이 native Fetch가 axios 보다 살짝 더 빠릅니다. 두 클라이언트 모두 비동기이기 때문에 크게 중요하지 않습니다.
 

정리

Axios
Fetch
라이브러리 설치 O
라이브러리 설치 X
자동 JSON 변환
JSON 변환 필요
자동 문자열 변환
"JSON.stringfy()"를 사용하여 객체를 문자열 변환
상대적으로 느림
속도가 상대적으로 빠름
상태코드가 범위를 넘어가면 거부
HTTP 에러 응답 시, promise 거부 x, 네트워크 장애시만 거부
CSRF 보호 기능으로 상대적으로 보안에 유리
X
Request 취소/ Request TimeOut 설정 가능
X, AbortController를 이용해야함
 

마무리

axios 라이브러리는 당연히 사용해오고 있어서 어떠한 이유로 사용하고 있는지 몰랐었다. 하지만 이번에 새로 조사하고 나니 fetch api 와 다르게 JSON, 문자열을 자동으로 변환해주고 CSRF 보호 기능이 있다는 사실을 알게되었다.
이러한 점을 보니 axios 라이브러리를 사용했기 때문에 코드를 더욱 쉽게 작성할 수 있었던 것 같다. 하지만 fetch의 장점도 있으니 프로젝트의 특성을 고려해서 사용하면 좋을 것 같다고 생각한다!

References