💻 Frontend
Axios
category
💻 Frontend
Axios특징설치Axios APIaxios(config)axios(url[,config])Axios 인스턴스axios.create([config])요청 configurlmethodbaseURLtransformRequesttransformResponseheadersparams응답 스키마Config 기본값전역 Axios 기본값커스텀 인스턴스 기본값Config 우선 순위인터셉터(interceptor)요청 취소Axios vs Fetch문법JSON 변환문자열 변환성능정리마무리References
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
인자를 순서대로 찾습니다. 다음은 예제입니다.우선순위
- instance config 인자
- 인스턴스
defaults
- 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 기반이기 때문에 성능 문제를 일으키지 않을 것입니다.
위 그래프에서 확인할 수 있듯이 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의 장점도 있으니 프로젝트의 특성을 고려해서 사용하면 좋을 것 같다고 생각한다!