axios가 fetch보다 무엇이 괜찮길래?!

이주영·2023년 6월 27일
0

알리고올리고

목록 보기
2/4
post-thumbnail

서론

Axios 라이브러리와 빌트인 Fetch API보다 무엇이 좋은지 정확히 알고 사용하려고 정리한다.

본론

사전 지식

  1. Promise 객체

    Promise 객체는 빌트인 실행 함수를 받는 것과 만들어진 Promise 객체를 사용하는 방식을 이해하면 어렵지 않다.

  • Promise 객체는 resolve와 reject를 받는다. 성공했을 때는 resolve라는 콜백함수로 status는 성공, result는 value가 들어가고 실패할 경우에는 status에는 거절됨, value에는 작성한 메세지가 들어간다.

  • 그렇게 만들어진 Promise 객체를 사용하는 위치에서는 .then와 .catch. 그리고 .finally를 사용할 수 있다. .then을 사용할 경우 첫 번째 인수는 성공했을 때 결과를 받고 두 번째 인수는 에러를 받는다. 만약 에러만 받고 싶다면 catch 메서드를 사용하면 된다. 만약 catch를 사용하지 않는다면 then(null, errorFunction)으로 동작은 그대로 재현할 수 있다. 성공과 실패 여부와 상관없는 동작을 하고 싶을 때 finally를 사용하면 된다.

  1. HTTP

  2. 런타임 환경

axios

자바스크립트 런타임 환경 (브라우저 및 Node.js) 에서 사용할 수 있는 Promise 기반의 HTTP 비동기 통신 라이브러리이다. 브라우저 환경에서는 XMLHttpRequests 객체를 사용하고 노드 환경에서는 http 모듈은 사용한다.

특징

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

출처 : 공식문서

axios vs fetch

  1. 브라우저를 위해 XMLHttpRequest 생성
  2. node.js 위해 http요청 생성
  3. Promise API 지원
  4. 요청 및 응답 인터셉트
  5. 요청 및 응답 데이터 변환
  6. 요청 취소
  7. JSON 데이터 자동 변환
  8. XSRF를 막기위한 클라이언트 사이드 지원
  9. status code : 200 ~ 300은 정상 그 외는 비정상으로 설정되어 있다.

그래서 실질적으로 axios의 장점이 무엇인가

인스턴스를 만들 수 있다?!

인스턴스를 만들 수 있다는 것은 재활용이 가능하다는 의미로 해석할 수 있다. 즉 하나의 인스턴스를 만들어놓으면 axios 요청 시 해당 인스턴스를 활용한다면 반복해서 작성했던 baseURL, timeout, header 등 한 군데에서 관리할 수 있게 된다.

const instance = axios.create({
  baseURL: env.BASE_API_URL,
  headers: {
    'Content-Type': 'application/json;charset=UTF-8',
  },
  withCredentials: true,
});

Timeout API를 제공해 준다

const instance = axios.create({
  baseURL: env.BASE_API_URL,
  headers: {
    'Content-Type': 'application/json;charset=UTF-8',
  },
  withCredentials: true,
  timeout: 10000, // 이 부분
});

위의 코드와 같이 네트워크 요청 시 최대 대기 시간을 설정할 수 있다. 이 부분은 정말 유용하고 타임아웃 예러 처리를 도와주는 axios의 API라고 생각한다. 대기 시간이 초과되면 error 객체를 내려주는데 code의 속성이 "ECONNABORTED"로 반환된다. 그러니 해당 값을 활용하면 네트워크 타임 아웃 에러를 캐치할 수 있게 도와준다. fetch는 이런 기능이 없어 네트 워크 요청 시 대기 시간에 대한 에러는 캐치하기 어렵다고 생각한다.

인터셉터가 왜 유용한 거야?!

then 또는 catch로 처리되기 전에 요청과 응답을 가로챌 수 있습니다.

말그대로 가로채는 역할을 하는데 서버로 보내는 요청과 클라이언트로 오는 응답을 가로챈다. 가로채서 도대체 무엇을 할 수 있는 걸까!?

  1. 요청을 가로챌땐
  • 요청 설정의 옵션을 바꿀 수 있다.
  • 로그인 관련하여 헤더를 추가하거나 수정할 수 있겠다.
  • 로깅
  • 로딩 상태를 관리할 수 있다.
  1. 응답을 가로챌땐
  • response data를 가공하거나 수정할 수 있다.
  • 에러를 핸들링할 수 있다.
  • 로깅
  • 상태를 관리할 수 있다.

몇 가지를 살펴보면

const onLoadingHandler = async(type:string) => { 
	const loadingStore = useLoadingStore();
	const {startLoading, stopLoading, cancelLoading} = loadingStore();

	switch (type) {
		case "request" :
			startLoading();
			break;
		case "response" :
			stopLoading();
			break;
		...
	}
	return Promise.resolve();
}

출처 : https://brunch.co.kr/@14e1a0684a6c4d5/6

와 같이 로딩 상태를 응답 인터셉터에서 관리할 수 있다. 마찬가지로 에러도 핸들링할 수 있을 것이다.


// 요청 인터셉터
instance.interceptors.request.use(
  function fullfilledRequestInterceptor(config) {
    // TODO 요청이 전달되기 전에 작업 수행
    // 액세스 토큰이 있다면 Authorization에 달기
    return config;
  },
  function rejectedRequestInterceptor(error) {
    // TODO 요청 오류가 있는 작업 수행
    return Promise.reject(error);
  },
);

// 응답 인터셉터
instance.interceptors.response.use(
  function fullfilledResponseInterceptor(response) {
    // NOTE 2xx 범위에 있는 상태 코드는 이 함수를 트리거 합니다.
    // TODO 응답 데이터가 있는 작업 수행
    return response;
  },
  function rejectedResponseInterceptor(error) {
    // NOTE 2xx 외의 범위에 있는 상태 코드는 이 함수를 트리거 합니다.
    // TODO 응답 오류가 있는 작업 수행
    return Promise.reject(error);
  },
);

이런 식으로 use 매소드를 활용하여 만들어놓은 axios 인스턴에서 설정한 인터셉터 함수를 저장할 수 있다.

URL - 인코딩 바디

검색 기능과 필터링 기능을 구현할 때 주로 URL의 쿼리 스트링을 활용하여 구현한다. 쿼리 스트링이라 함은 도메인 이후 파라미터 (/path)가 들어가고 맨 끝에 (?key="something"&sort="createdAt") 이런식 으로 추가하여 전역적으로 상태를 가지고 있도록 하는 방법을 말한다. 하지만 URL을 다루는 데는 기존에는 URL 객체와 URLSearchParams 객체를 생성자 함수로 구현하여 해당 인스턴스에 종속된 메소드를 활용해서 안전한 URL 설정 및 변경을 구현할 수 있었다.

fetch를 사용했다면 URLSearchParams 객체를 생성한 후 append 매소드를 사용하여 추가해야 했을 것이다.

const params = { page: 1, limit: 10 }; 
const queryParams = new URLSearchParams(params);

fetch(`https://api.example.com/posts?${queryParams}`).then(res => res.json())

axios는 이 부분을 더욱 편리하게 해 준다.

const params = {
  page: 1,
  limit: 10
};

axios.get('https://api.example.com/user', { params }) // ?page=1&limit=10 URL 인코딩
.then(res => console.log(res))

그거 객체만 만들어서 넣어주면 되는 것. 자동으로 url 인코딩을 해준다.

결론

결론적으로 자바스크립트에서 제공해 주는 fetch 메소드보다 4가지 방면에서 장점이 있다.

  1. 통신 로직을 모듈화 하기 용이하다는 것
  2. 네트워크 에러 처리를 할 수 있다는 것
  3. 서비스 운영하는데 있어 로깅과 에러 처리를 할 수 있는 환경이 하나 추가된 것
  4. 자동 직렬화와 URL 인코딩을 자동적으로 해줘 개발자로 하여금 통신 그 자체에 집중하게 해준다는 것
profile
https://danny-blog.vercel.app/ 문제 해결 과정을 정리하는 블로그입니다.

0개의 댓글