티스토리 뷰

TIL

AXIOS 사용해보기

윤미주 2024. 2. 17. 13:17

Axios를 사용하는 이유 알고가기 ..❗

Fetch와 Axios 의 장단점

Fetch 
- 장점
● 자바스크립트의 내장 API이다. (추가적인 의존성 관리 필요 ❌)
● 가볍다.

- 단점
● 쿠키를 보내거나 받지 않는다.
● 오류처리가 직관적이지 않다. (오류 처리를 위한 추가적인 로직 필요)
●기본적인 기능만 제공. (인터셉터, 타임아웃 설정, 폼데이터 제출 등의 고급 기능 미제공)
● 브라우저 기반 API로 Node.js 서버에서 사용 불가.

 

Axios
- 장점
● 브라우저와 Node.js 모두에서 사용 가능.
● 자동 JSON 데이터 변환 .
● 인터셉터 기능. (요청이나 응답을 가로채어 로직을 추가할 수 있음)
● 타임아웃 설정, 쿠키 전송 등의 고급 설정 지원.

- 단점
● 외부 라이브러리 의존성.
● 많은 기능을 제공하기 때문에 파일의 크기가 커 무거움.

 

 

1. 설치 하기

$ npm install axios
$ yarn add axios

 

 

2. 폴더와 파일 만들기

api📁

ㄴ axiosInstance.js

ㄴ request.js

 

3. env.local 환경변수로 server URL 작성하기

//yarn
REACT_APP_SERVER_URL=http://localhost:5000/

//vite
VITE_SERVER_URL="http://localhost:5000/"

 

 

3. axiosInstance.js 작성하기

instance를 생성하는 이유

  • axios에서 사용되는 class는 axios 라이브러리 내부에 정의되어있다.
  • class를 기반으로 인스턴스를 생성하면, 내부에서 다양한 처리들을 할 수 있다.
  • 한 곳에서 관리되기 때문에 코드중복을 줄이고 유지보수에 용이하다.
import axios from "axios";
import requests from "./request";

const axiosInstance = axios.create({
  baseURL: process.env.REACT_APP_SERVER_URL,
  headers: {
    "Content-Type": "application/json",
  },
  params: {
    id: "",
    nickname: "",
  },
  responseType: "json",
});

async function fetchPostInstance() {
  try {
    const responseLetters = await axiosInstance.get(requests.fetchLetters);
    console.log(responseLetters.status);
  } catch (error) {
    console.error(error);
    if (error.response) {
      console.error(error.response.status);
    }
  }

  try {
    const responseUserInfo = await axiosInstance.get(requests.fetchUserInfo);
    console.log(responseUserInfo.status);
  } catch (error) {
    console.error(error);
    if (error.response) {
      console.error(error.response.status);
    }
  }
}

export { axiosInstance, fetchPostInstance };

 

위 코드를 작성하면서 당연하지만 몰랐던 멍청한 실수로 인해 2시간을 잡아먹었다...

잊지말기 이쫘식아..!!

https://anywhereim.tistory.com/57

 

TypeError: _api_axiosInstance_WEBPACK_IMPORTED_MODULE_11__

에러가 없는 데이터 가져오기 실패와 더불어 해당 에러까지 포함해 2시간을 잡아먹은...!! 물론 환경변수를 불러오는 부분에서도 문제가 있었다. 하지만 그때는 에러없이 axios에서 값 자체를 받

anywhereim.tistory.com

 

 

const axiosInstance = axios.create({
  baseURL: process.env.REACT_APP_SERVER_URL,
  headers: {
    "Cache-Control": "no-cache",
    "Content-Type": "application/json",
  },
  timeout: 3000,
  params: {
    id: "",
    nickname: "",
  },
  responseType: "json",
});

 

baseURL
일일히 서버의 기본 URL을 입력해주는 수고를 덜수 있다.
예를 들어 baseURL이 http://localhost:5000 라면, 매번 http://localhost:5000주소를 넣어주어야 하는데 
instance에 baseURL을 설정해 주면 모든 경로의 앞에 기본값으로 넣어준다

 

 

headers
Cache-Control
- HTTP요청과 응답에 대한 캐싱 동작을 제어
     no-cache는 요청에 대해 캐시된 응답을 사용하지 않도록 지시하는 역할을 해준다.
     즉, 항상 서버로부터 새로운 데이터를 받아와야 한다!
     cors에러가 발생된다면 지워주기..ㅎ
🔥캐싱은 이전에 수행한 요청이나 응답 결과를 재사용해 네트워크성능을 향상, 대역폭을 줄일 수 있음🔥

public, max-age=0 (미설정 시 기본값)
- 캐시된 응답이 즉시 만료되도록 지정
     즉, 매요청마다 서버로부터 리소스를 다시 가져와야 한다.

 

● Content-Type
- application/json은 서버에 보내는 데이터의 타입이 JSON 형식임을 나타낸다.
● timeout
- 요청에 대한 응답을 기다리는 최대 시간을 미리초 단위로 설정. 정해둔 시간이내에 응답을 받지 못하면 실패처리
● params
- 요청 URL에 추가될 쿼리 파라미터를 설정한다. 동일한 쿼리 파라미터를 추가 할 때 유용
● responseType
- 서버로부터 받아올 데이터 타입을 지정

 

💡  responseLetters 에러처리

  try {
    const responseLetters = await axiosInstance.get(requests.fetchLetters);
    console.log(responseLetters.status);
  } catch (error) {
    console.error(error);
    if (error.response) {
      console.error(error.response.status);
    }
  }

 

 

 

💡  responseUserInfo 에러처리

  try {
    const responseUserInfo = await axiosInstance.get(requests.fetchUserInfo);
    console.log(responseUserInfo.status);
  } catch (error) {
    console.error(error);
    if (error.response) {
      console.error(error.response.status);
    }

 

 

💡  header timeout에 대한 재시도 처리

  axiosInstance.interceptors.response.use(undefined, async (error) => {
    const { config, response } = error;
    const retry = config.retry || 3;
    const delay = config.retryDelay || 1000;

    if (response && retry > 0) {
      config.retry -= 1;
      await new Promise((resolve) => setTimeout(resolve, delay));
      return axiosInstance(config);
    }
    return Promise.reject(error);
  });

 

이 부분은 설명이 필요할 것 같아서 최대한 간략하게 설명하려 노력해보자.. 

● axios.interceptors.response.use 메서드는 두개의 함수를 인자로 받는다. 
①응답이 성공적일때, 
②에러를 반환했을 때

● 첫번째 자리에 undefined를 넣어준 이유
   해당 코드는 성공에 대한 로직을 처리하기 위한 코드가 아닌,
   실패한 응답에 대한 처리를 하기 위해 작성된 코드이므로 성공시에 대한 처리 자체를 undefined로 넣어주었다.

● config 객체 ?
   error객체 내에 config는 axios가 요청을 보낼 때 사용한 설정을 담고 있다.
   즉, config 객체에는 URL, 헤더, 파라미터 등 요청에 관한 모든 정보가 포함되어 있다.
   때문에  config를 수정해 재요청을 보낼 수 있다. 
   그래서 retry와 retryDelay 같은 추가 속성을 이용해 재시도 로직을 만들었다.

● new Promise
   js의 Promise 객체를 생성하는 생성자이다!
   Promise는 비동기 작업의 최종 완료 또는 실패 및 그 결과값을 보여준다.
  
  ✅ await new Promise((resolve) => setTimeout(resolve, delay))

  위 코드는 new Promise의 결과값을 받아 delay 이후에 비동기 작업이 성공적으로 완료된 후 resolve함수를 호출
  resolve는 Promise가 성공적으로 완료되었을 때 호출되어,
  지정된 시간만큼 대기 후 재시도 로직을 계속 진행할 수 있다.

 

 

 

4. fetchPostInstance 사용하기

function App() {
  useEffect(() => {
    fetchPostInstance();
  }, []);
  return <RouterProvider router={router} />;
}

 

가장 상위에서 마운트 되었을때 값을 받아와 유지해야 하는 값이 있으므로

가장 상단에서 에러처리가 가능하도록 설정해 두었다.

 

 

5. request.js 작성하기

const requests = {
  fetchLetters: `/letters`,
  fetchUserInfo: `/login`,
};

export default requests;

모든 경로에 대한 변수명을 지정해 주고,

이후 컴포넌트에서는 경로의 주소값을 직접적으로 입력하는 것이 아닌 변수로 작성할 수 있도록 만들어 두었다.

 

예를 들어 instance에 baseURL을 설정해두었음으로 

letters 경로 전체주소를 입력 할때 axiosinstance.get(requests.fetchLetters) 로 입력하여 사용 가능

 

 

'TIL' 카테고리의 다른 글

Input Custom Hook 만들어보기  (0) 2024.02.20
.env.local 환경변수 사용하기  (0) 2024.02.20
useNavigate & <Link />  (1) 2024.02.16
HTTP  (1) 2024.02.16
Json Server  (0) 2024.02.16