Axios는 node.js와 브라우저의 통신을 위한 Promise 기반 HTTP 클라이언트 이다.
서버 사이드에서는 native node.js의 http
모듈을 사용하고 클라이언트(브라우저)에서는 XMLHttpRequests를 사용한다.
const axios = require('axios');
// 지정된 ID를 가진 유저에 대한 요청
axios.get('/user?id=123')
.then((response) => {
// 성공 핸들링
console.log(response)
})
.catch((error) => {
// 에러 핸들링
console.log(error)
})
.finally(() => {
// 항상 실행되는 영역 (실패든 성공이든)
})
또는 다음과 같이 실행 할 수 있다.
axios.get('/user', {
params: {
id: 123
}
})
// 생략
async/await
를 사용하려면 외부 함수를 async
로 선언해야 한다.
async function getUser() {
try {
const response = await axios.get('/user?id=12345');
console.log(response);
} catch (error) {
console.error(error);
}
}
POST
요청 생성 (JSON)
// 유저를 등록하는 요청
axios.post('/user', {
firstName: 'Sam',
lastName: 'Smith'
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
동시에 여러 요청 생성
function getUserAccount() {
return axios.get('/user/123');
}
function getUserPermissions() {
return axios.get('/user/123/permissions');
}
Promise.all([getUserAccount(), getUserPermissions()])
.then((results) => {
const acct = results[0];
const perm = results[1];
});
HTML form을 JSON으로 POST 요청
const {data} = await axios.post('/user', document.querySelector('#my-form'), {
headers: {
'Content-Type': 'application/json'
}
})
Forms
multipart/form-data
)const {data} = await axios.post('https://somewhere.org/post', {
firstName: 'Sam',
lastName: 'Smith',
orders: [1, 2, 3],
photo: document.querySelector('#fileInput').files
}, {
headers: {
'Content-Type': 'multipart/form-data'
}
}
)
application/x-www-form-urlencoded
) const {data} = await axios.post('https://somewhere.org/post', {
firstName: 'Sam',
lastName: 'Smith',
orders: [1, 2, 3],
photo: document.querySelector('#fileInput').files
}, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
)
요청의 마지막 인자로 config 객체를 전달하여 관련 설정을 보낼 수 있다.
axios(config)
// POST 요청
axios({
method: 'post',
url: '/user/123',
data: {
firstName: 'Sam',
lastName: 'Smith'
}
});
// node.js에서 원격 이미지를 요청하는 GET 요청
axios({
method: 'get',
url: 'http://bit.ly/2mTM3nY',
responseType: 'stream'
})
.then(function (response) {
response.data.pipe(fs.createWriteStream('some_image.jpg'))
});
사용자 지정 config로 새 axios 인스턴스를 만들 수 있다.
axios.create([config])
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
request에 대한 response는 아래의 정보를 가지고 있다.
{
// 서버가 제공하는 응답
data: {},
// HTTP 상태 코드
status: 200,
// HTTP 상태 메시지
statusText: 'OK',
// HTTP 헤더
// 모든 헤더 이름은 소문자이며, 괄호 표기법을 사용하여 접근할 수 있다.
// 예시: `response.headers['content-type']`
headers: {},
// 요청을 위해 `Axios`가 제공하는 구성
config: {},
// 이번 응답으로 생성된 요청
// node.js에서는 마지막 ClientRequest 인스턴스
// 브라우저에서는 XMLHttpRequest
request: {}
}
then
을 사용하면 아래와 같은 response를 받는다.
axios.get('/user/123')
.then(function (response) {
console.log(response.data);
console.log(response.status);
console.log(response.statusText);
console.log(response.headers);
console.log(response.config);
});
catch
를 사용하거나, 거부 콜백 함수를 then
의 두번째 인자로 넘길 시, 에러 핸들링에서 설명된 error
객체를 사용할 수 있다.
전역 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';
커스텀 instance 기본값
// 인스턴스를 생성할때 config 기본값 설정하기
const instance = axios.create({
baseURL: 'https://base_url.com'
});
// 인스턴스를 만든 후 기본값 변경하기
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
Config 우선 순위
config는 우선 순위에 따라 병합된다.
lib/defaults.js
라이브러리에서 기본값, 인스턴스의 defaults
속성, 요청의 config
인자를 순서대로 찾는다.
then
또는 catch
로 처리되기 전에 요청과 응답을 가로챌 수 있다.
// 요청 인터셉터 추가하기
axios.interceptors.request.use((config) => {
// 요청이 전달되기 전에 작업 수행
return config;
}, (error) => {
// 요청 오류가 있는 작업 수행
return Promise.reject(error);
});
// 응답 인터셉터 추가하기
axios.interceptors.response.use((response) => {
// 2xx 범위에 있는 상태 코드는 이 함수를 트리거
// 응답 데이터가 있는 작업 수행
return response;
}, (error) => {
// 2xx 외의 범위에 있는 상태 코드는 이 함수를 트리거
// 응답 오류가 있는 작업 수행
return Promise.reject(error);
});
필요할 때 interceptor를 제거할 수 있다.
const myInterceptor = axios.interceptors.request.use(() => {/*...*/});
axios.interceptors.request.eject(myInterceptor);
커스텀 인스턴스에서도 interceptor를 추가할 수 있다.
const instance = axios.create();
instance.interceptors.request.use(() => {/*...*/});
axios.get('/user/12345')
.catch((error) => {
if (error.response) {
// 요청이 전송되었고, 서버는 2xx 외의 상태 코드로 응답
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
// 요청이 전송되었지만, 응답이 수신되지 않음
// 'error.request'는 브라우저에서 XMLHtpRequest 인스턴스이고,
// node.js에서는 http.ClientRequest 인스턴스이다.
console.log(error.request);
} else {
// 오류가 발생한 요청을 설정하는 동안 문제가 발생
console.log('Error', error.message);
}
console.log(error.config);
});
config 옵션 중 validateStatus
를 사용하면, 오류를 발생시키는 HTTP 상태 코드를 정의할 수 있다.
axios.get('/user/123', {
validateStatus: (status) => {
return status < 500; // 상태 코드가 500 미만인 경우에만 해결
}
})
toJSON
을 사용하면 HTTP 에러에 대한 더 많은 정보를 객체 형식으로 가져온다.
axios.get('/user/123')
.catch((error) => {
console.log(error.toJSON());
});
취소 토큰을 이용하여 요청을 취소할 수 있다.
아래와 같이 CancelToken.source
팩토리를 사용하여 취소 토큰을 만들 수 있다.
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/user/123', {
cancelToken: source.token
}).catch((thrown) => {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// 에러 핸들링
}
});
axios.post('/user/123', {
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((c) => {
// 실행자 함수는 취소 함수를 파라미터로 받습니다.
cancel = c;
})
});
// 요청 취소하기
cancel();
보통 axios는 JSON을 사용한다. application/x-www-form-urlencoded
포맷으로 데이터를 전송하려면 다음 옵션 중 하나를 사용할 수 있다.
브라우저
브라우저에서는 URLSearchParams
API를 사용할 수 있다.
const params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);
Node.js
querystring
모듈
const querystring = require('querystring');
axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));
url module
의 URLSearchParams
const url = require('url');
const params = new url.URLSearchParams({ foo: 'bar' });
axios.post('http://something.com/', params.toString());
qs
라이브러리
Form data
node.js에서 다음과 같이 form-data
라이브러리를 사용할 수 있다.
const FormData = require('form-data');
const form = new FormData();
form.append('my_field', 'my value');
form.append('my_buffer', new Buffer(10));
form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
axios.post('https://example.com', form, { headers: form.getHeaders() })
interceptor를 사용할수도 있다.
axios.interceptors.request.use(config => {
if (config.data instanceof FormData) {
Object.assign(config.headers, config.data.getHeaders());
}
return config;
});
회사에서 진행한 프로젝트에서 axios를 사용하게 되어 axios 공식 홈페이지의 docs를 보며 정리한 내용이다.
사용법도 어렵지 않고 커스텀 인스턴스를 만들 수 있는 점이나 인터셉터를 활용한 로그인 여부 처리, 에러 페이지 보여주기 등 유용한 라이브러리였다.