fetch와 axios 비교
웹 개발에서 데이터를 비동기적으로 가져오는 것은 매우 일반적인 작업이다. 이를 위해 주로 사용되는 두 가지 도구가 있는데, 바로 fetch와 axios이다. 참고로 이들은 구식 브라우저에서는 지원하지 않으므로 폴리필이 필요하다.
Fetch
정의 :
웹 브라우저 내장 API로, 네트워크 요청을 비동기적으로 처리하기 위해 만들어졌다.
const res = await fetch(url);
res.status; // response 코드
res.headers; // response 헤더
// response body
await res.json(); // JSON 문자열을 파싱해서 자바스크립트 객체로 변환함.
await res.text(); // 문자열을 그대로 가져옴.
res.json()
: 바디의 JSON 문자열을 파싱해서 자바스크립트 객체로 변환res.text()
: 바디의 내용을 문자열로 그대로 가져옴.만약 body의 내용이 JSON이 아닌데 res.json으로 파싱하면 오류가 남.
fetch() 옵션
method (메소드)
GET, POST, PATCH, DELETE
지정하지 않으면 기본 값이 GET
headers (헤더)
Content-Type
Authorization
body (바디)
자바스크립트 객체는 그대로 전달할 수 없기 때문에 JSON 문자열로 바꿔줘야 함.
장점 :
웹 표준:
Fetch는 웹 표준으로, 모든 최신 브라우저에서 기본적으로 지원된다.
웹 표준 API로서의 Fetch는 setTimeout, console 등과 함께 자주 사용된다.
단점 :
추가 구현 필요:
Fetch를 사용할 때는 axios와 비교하여 수동으로 구현해야 하는 기능들이 있다.
예를 들어, 요청과 응답을 중간에 가로채어 처리하는 Interceptor 기능은 직접 작성해야 한다.
// 요청을 보내기 전에 수행할 작업 const requestInterceptor = (url, options) => { console.log('Request Interceptor:', url, options); // 예: 인증 토큰 추가 const modifiedOptions = { ...options, headers: { ...options.headers, 'Authorization': 'Bearer YOUR_TOKEN' } }; return { url, options: modifiedOptions }; }; // 응답을 받은 후에 수행할 작업 const responseInterceptor = async (response) => { console.log('Response Interceptor:', response); if (!response.ok) { const errorData = await response.json(); throw new Error(`Error: ${response.status} - ${errorData.message}`); } return response.json(); }; const fetchWithInterceptors = async (url, options) => { const { url: interceptedUrl, options: interceptedOptions } = requestInterceptor(url, options); try { const response = await fetch(interceptedUrl, interceptedOptions); return await responseInterceptor(response); } catch (error) { // 에러 처리 console.error('Fetch Error:', error); throw error; } }; // 사용 예시 fetchWithInterceptors('https://api.example.com/data', { method: 'GET' }) .then(data => console.log('Data:', data)) .catch(error => console.error('Error:', error));
응답값 파싱:
Fetch는 기본적으로 응답값을 자동으로 파싱하지 않는다.
응답을 JSON 형식으로 변환하려면
res.json()
메서드를 호출해야 한다. 이는 코드 작성 시 추가 단계를 필요로 한다.
fetch('https://api.example.com/data') .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error));
에러 핸들링:
HTTP 오류 상태 코드(예: 404, 500)는 Fetch에서는 자동으로 에러로 처리되지 않는다.
Fetch API에서는 HTTP 상태 코드가 200-299 범위가 아니어도 네트워크 요청이 성공하면
Promise
를 반환한다. 따라서 상태 코드에 따라 별도로 오류를 처리해야한다. 이를 위해res.status
를 사용하여 각 상태 코드에 대한 처리를 세분화할 수 있다.
export async function getColorSurvey(id) { const res = await fetch(`https://www./${id}`); if (!res.ok) { throw new Error('데이터를 불러오는데 실패했습니다.'); } const data = await res.json(); return data; }
export async function getColorSurvey(id) {
const res = await fetch(`https://www.example.com/${id}`);
// 상태 코드에 따라 오류 메시지를 다르게 처리
if (!res.ok) {
if (res.status >= 400 && res.status < 500) {
throw new Error('클라이언트 오류가 발생했습니다. 요청을 다시 확인하세요.');
} else if (res.status >= 500) {
throw new Error('서버 오류가 발생했습니다. 나중에 다시 시도하세요.');
} else {
throw new Error('알 수 없는 오류가 발생했습니다.');
}
}
const data = await res.json();
return data;
}
axios
정의 :
브라우저와 Node.js 환경 모두에서 동작하는 HTTP 클라이언트 라이브러리
axios는 HTTP 메소드 이름과 동일한 메소드를 사용하고 리스폰스 바디를 data 프로퍼티로 접근할 수 있다.
axios 옵션
GET, DELETE Request
Request body가 필요 없기 때문에 옵션을 두 번째 아규먼트로 받는다.
POST, PATCH, PUT
Request
Request에 보낼 body 내용은 두 번째 아규먼트로 받고, 옵션을 세 번째 아규먼트로 받는다.
별도의 파싱과정이 없이 JSON으로 변환된다.
// Axios 모듈 가져오기 import axios from 'axios'; // GET 요청 (Request Body 없음) axios.get('https://api.example.com/data', { // 옵션 params: { id: 123 }, headers: { 'Authorization': 'Bearer token123' } }) .then(response => { console.log(response.data); }) .catch(error => { console.error('에러 발생:', error); }); // DELETE 요청 (Request Body 없음) axios.delete('https://api.example.com/data/123', { // 옵션 headers: { 'Authorization': 'Bearer token123' } }) .then(response => { console.log(response.data); }) .catch(error => { console.error('에러 발생:', error); });
// POST 요청 (Request Body 있음) axios.post('https://api.example.com/data', { name: 'John Doe', age: 30 }, { // 옵션 headers: { 'Authorization': 'Bearer token123' } }) .then(response => { console.log(response.data); }) .catch(error => { console.error('에러 발생:', error); }); // PATCH 요청 (Request Body 있음) axios.patch('https://api.example.com/data/123', { age: 31 }, { // 옵션 headers: { 'Authorization': 'Bearer token123' } }) .then(response => { console.log(response.data); }) .catch(error => { console.error('에러 발생:', error); }); // PUT 요청 (Request Body 있음) axios.put('https://api.example.com/data/123', { name: 'Jane Doe', age: 25 }, { // 옵션 headers: { 'Authorization': 'Bearer token123' } }) .then(response => { console.log(response.data); }) .catch(error => { console.error('에러 발생:', error); });
axios 인스턴스
리퀘스트마다 공통되는 부분이 있으면 axios.create()으로 인스턴스를 생성한다.
해당 인스턴스로 리퀘스트를 보내면 된다.
const axios = require('axios'); // Axios 인스턴스 생성 const instance = axios.create({ baseURL: 'https://api.example.com/', // 기본 URL 설정 timeout: 5000, // 타임아웃 설정 (밀리초) headers: { 'Authorization': 'Bearer token123' // 기본 헤더 설정 } });
// GET 요청 예제 instance.get('/data') .then(response => { console.log(response.data); }) .catch(error => { console.error('에러 발생:', error); }); // POST 요청 예제 instance.post('/data', { name: 'John Doe', age: 30 }) .then(response => { console.log(response.data); }) .catch(error => { console.error('에러 발생:', error); });
https://axios-http.com/docs/instance
참고 :
Fetch() 함수는 원래 웹 브라우저에서만 사용할 수 있었으며, Node.js에서는 사용할 수 없었다.
그러나 Node.js v17.5부터 실험적인 기능으로 Fetch가 도입되었고, 이에 따라 주의 메시지가 출력되었다.
이후, Node.js v18.13부터는 이 기능이 안정화되어 더 이상 주의 메시지가 출력되지 않는다.
장점 :
간편한 코드 작성 : 코드 작성이 간편하다.
직관적인 문법 : 문법이 직관적이다.
다양한 기능 : 인터셉터, 타임아웃, 요청 취소 등의 기능을 제공한다.
에러 처리 용이 : catch 블록에서 에러 처리가 가능하다.
자동 JSON 파싱 : 응답 데이터(res.data)는 자동으로 JSON으로 파싱된다.
(텍스트로 파싱이 필요할 경우 res.text()를 사용하면 된다.)
axios.get('https://api.example.com/data')
.then(response => {
console.log(response.data); // JSON 데이터, response.json() 불필요
})
.catch(error => {
console.error('Error:', error);
});
단점 :
번들 사이즈 증가 : axios는 많은 기능을 제공하지만 그만큼 번들 사이즈를 증가시킨다. 특히 번들 사이즈가 커지면 로딩 시간이 길어질 수 있다.
axios의 기능 3개 :
1) 인터셉터
axios의 인터셉터는 요청과 응답을 가로채고 수정할 수 있는 기능이다. 이를 통해 전역적으로 요청과 응답을 처리하거나, 특정 상황에 맞게 헤더를 추가하거나 변경할 수 있다. 예를 들어, 모든 요청에 인증 토큰을 추가하거나, 응답 데이터를 특정 형식으로 변환하는 등의 작업을 수행할 수 있다.
모든 요청에 대해 인증 토큰 추가하기
axios.interceptors.request.use(config => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
}, error => {
return Promise.reject(error);
});
응답에 대한 에러 처리하기
axios.interceptors.response.use(response => {
// 응답이 성공인 경우
return response;
}, error => {
// 응답이 에러인 경우
if (error.response.status === 401) {
// 인증 오류 처리
} else if (error.response.status === 404) {
// 리소스를 찾을 수 없음 처리
} else {
// 기타 오류 처리
}
return Promise.reject(error);
});
요청 또는 응답에 대한 로깅
axios.interceptors.request.use(config => {
console.log('요청 시작:', config);
return config;
});
axios.interceptors.response.use(response => {
console.log('응답 받음:', response);
return response;
}, error => {
console.error('에러 발생:', error);
return Promise.reject(error);
});
2) 타임아웃
axios는 요청에 대한 응답을 기다리는 시간을 설정할 수 있는 타임아웃 기능을 제공한다.
이를 사용하여 서버로의 요청에 대한 응답이 지연되는 경우, 일정 시간이 지난 후에 요청을 취소하고 에러를 발생시킬 수 있다.
axios.get('/api/data', { timeout: 5000 })
.then(response => {
// 성공적으로 데이터를 받았을 때의 처리
})
.catch(error => {
// 타임아웃 또는 다른 에러 처리
});
3) 요청 취소 기능
axios는 요청을 취소하는 기능을 제공하여, 요청이 보내진 후에도 요청을 중단시킬 수 있다.
이는 사용자가 요청을 취소하고 다른 작업을 수행할 때 유용하다.
const source = axios.CancelToken.source();
axios.get('/api/data', {
cancelToken: source.token
})
.then(response => {
// 성공적으로 데이터를 받았을 때의 처리
})
.catch(error => {
if (axios.isCancel(error)) {
// 요청이 취소된 경우 처리
} else {
// 다른 에러 처리
}
});
// 요청 취소
source.cancel('요청이 사용자에 의해 취소되었습니다.')
댓글을 작성해보세요.