Skip to content

fetch vs axios

Sunny edited this page Nov 22, 2024 · 1 revision

fetch와 axios

fetch

  • 웹 브라우저에서 사용할 수 있는 Web API
  • HTTP 통신으로 서버로부터 데이터를 가져올 수 있다.
  • Promise 기반으로 비동기 통신을 지원한다.
  • 별도의 설치 없이 바로 사용할 수 있다.

axios

  • node.js와 브라우저를 위한 Promise 기반 HTTP 클라이언트
  • 각 웹 브라우저의 하위호환성(Cross-Browser Compatibility) 지원
  • 자동 JSON 데이터 변환

fetch와 axios의 차이

설치 여부

  • fetch: fetch는 자바스크립트에서 기본적으로 제공하는 웹 API이기 때문에 별도의 설치가 필요 없고, 업데이트에 따른 오류 예방이 가능하다.
  • axios: 별도로 설치해야 하는 라이브러리라서 업데이트에 따라 불안정할 수 있다.

데이터 응답

  • fetch: 가져온 데이터는 **.json을 통해 분석(Parsing)**해야 한다.

    ;(async () => {
      // const res = await fetch('<https://api.heropy.dev/v0/users>', { method: 'GET' })
      const res = await fetch('<https://api.heropy.dev/v0/users>')
      const data = await res.json()
      console.log(data)
    })()
    
  • axios: 응답 객체의 data 속성을 통해 접근할 수 있다.

    import axios from 'axios'
    

    ;(async () => { // const res = await axios({ url: '<https://api.heropy.dev/v0/users>', method: 'GET' }) // const res = await axios.get('<https://api.heropy.dev/v0/users>') const res = await axios('<https://api.heropy.dev/v0/users>') console.log(res.data) })()

GET 쿼리

  • fetch

    • URL에 직접 쿼리스트링 포함

      ;(async () => {
        const res = await fetch('<https://omdbapi.com/?apikey=7035c60c&s=avengers>', {
          method: 'GET'
        })
        const data = await res.json()
        console.log(data)
      })()
      
    • 쿼리 정보를 객체 형식으로 가진 경우에는 URLSearchParams 클래스를 사용할 수도 있음

      const queries = new URLSearchParams({
        apikey: '7035c60c',
        s: 'avengers'
      })
      console.log(queries.toString()) // 'apikey=7035c60c&s=avengers'
      

      ;(async () => { const res = await fetch(https://omdbapi.com/?${queries}, { method: 'GET' }) const data = await res.json() console.log(data) })()

  • axios

    • URL에 직접 쿼리스트링 포함

      ;(async () => {
        const res = await axios.get(`https://omdbapi.com/?apikey=7035c60c&s=avengers`)
        console.log(res.data)
      })()
      
    • params 옵션으로 객체 형식의 쿼리 정보 전달

      ;(async () => {
        const res = await axios({
          url: `https://omdbapi.com/`,
          method: 'GET',
          params: {
            apikey: '7035c60c',
            s: 'avengers'
          }
        })
        console.log(res.data)
      })()
      

데이터 전송

POST, PUT 등 데이터를 보내야 하는 요청을 보낼 때는 요청에 데이터를 담아서 보내야 한다. 이때, fetch 함수와 axios가 데이터를 보내는 방식이 조금 다르다.

  • fetch : body 옵션을 사용하여 데이터를 전송한다. 전송할 데이터의 타입을 application/json으로 지정 후, JSON.stringify 메서드를 통해 직렬화해서 body에 담는다.

    const res = await fetch('<https://api.heropy.dev/v0/users>', {
    	method: 'POST',
    	headers: {
    		'Content-Type': 'application/json',
      },
      body: JSON.stringify({
    	  name: "Boocam",
    	  age: 9
      })
    });
    

    const data = await res.json(); console.log(data);

  • axios : body가 아닌 data 옵션을 사용한다. fetch와 다르게 별도의 문자화 작업이 필요하지 않고, 자동으로 JSON으로 변환된다.

    const res = await axios({
    	url: '<https://api.heropy.dev/v0/users>',
    	method: 'POST',
    	headers: {
    		'Content-Type': 'application/json',
      },
      data: {
    	  name: "Boocam",
    	  age: 9
    })
    

    console.log(res.data);

에러 처리

  • fetch: fetch 함수는 응답 상태에 대해 Promise를 거부(reject)하지 않는다. 오직 네트워크 실패나 요청이 완전히 불가능한 경우에만 거부한다.

    예를 들어, 응답의 상태 코드가 401인 경우에도 Promise가 reject되지 않는다.

    따라서 다음과 같이 응답 객체의 속성을 명세에 맞게 확인한 후, 에러를 수동으로 처리해야 한다.

    ;(async () => {
      try {
        const res = await fetch('<https://omdbapi.com/?apikey=&s=avengers>') // Error: 401 Unauthorized!
        const data = await res.json() // { Response: 'False', Error: 'No API key provided.' }
        if (data.Response === 'False') {
          return console.error(data.Error) // 'No API key provided.'
        }
        console.log(data)
      } catch (err) {
        console.error('Error:', err)
      }
    })()
    
  • axios: **정상 처리(2xx)가 아닌 응답 상태 코드에 대해 자동으로 Promise를 거부(Reject)**하기 때문에 사용이 편리하다.

    ;(async () => {
      try {
        const res = await axios('<https://omdbapi.com/?apikey=&s=avengers>') // Error: 401 Unauthorized!
        console.log(res.data)
      } catch (err) {
        console.error('Error:', err) // { name: 'AxiosError', message: 'Request failed with status code 401', ... }
      }
    })()
    

시간 초과

<aside> ❗

네트워크 요청에서 특정 시간 내에 응답이 오지 않으면 요청을 중단할 수 있다. 이를 통해 무한 대기 현상을 방지하고, 불필요한 네트워크 트래픽을 줄이는 효과를 얻을 수 있다.

</aside>

  • fetch: 기본적으로 시간 초과 설정이 없기 때문에 별도의 작업이 필요하다. 다음과 같이 Promise.race 정적 메서드를 통해 먼저 처리되는 약속을 반환하도록 함수를 작성하고 사용할 수 있다.

    function fetchWithTimeout(url, options, timeout = 1000) {
      return Promise.race([
        fetch(url, options),
        new Promise((_, reject) =>
          setTimeout(() => reject(new Error('Request timed out!')), timeout)
        )
      ])
    }
    

    ;(async () => { try { await fetchWithTimeout('<https://api.heropy.dev/v0/delay?t=3000>', { method: 'GET' }, 2000) } catch (err) { console.log('Error:', err) } })()

  • axios: timeout 옵션을 통해 시간 초과 설정을 쉽게 추가할 수 있다.

    ;(async () => {
      try {
        await axios({
          url: '<https://api.heropy.dev/v0/delay?t=3000>',
          method: 'GET',
          timeout: 2000 // 2초
        })
      } catch (err) {
        console.log('Error:', err)
      }
    })()
    

차이 요약

  fetch axios
설치 브라우저 내장 API, 설치 불필요 외부 라이브러리, 설치 필요
데이터 처리 .json() 으로 직접 변환 필요 response.data로 바로 접근
쿼리 파라미터 - URL에 직접 작성
- URLSearchParams 사용
 - URL에 직접 작성
- params 옵션으로 객체 전달
데이터 전송 body에 JSON.stringify() 필요 data 옵션에 객체 직접 전달
에러 처리 네트워크 에러만 reject, 나머지 수동 처리 HTTP 에러 상태 자동 reject
타임아웃 별도 구현 필요 (Promise.race 활용) timeout 옵션으로 간단 설정

무엇을 쓸까?

axios를 사용하기로 결정했다.

  • 데이터를 보내고 받을 때 변환을 하지 않아도 된다
  • 에러 처리 시에 응답의 status code로도 Promise를 reject해준다
  • 타임아웃 처리가 쉽다

이러한 장점들로 인해 axios를 사용하기로 결정했다.

참고 자료

👥 팀 강점

🧑‍💻 개발 일지

📌 ALL

📌 FE

📌 BE

💥 트러블 슈팅

📌 FE

📌 BE

🤔 고민

📚 학습 정리

📌 김광현

📌 백지연

📌 전희선

📌 한승헌

🤝 회의록

🗒️ 데일리 스크럼

💬 팀 회고


👨‍👩‍👧‍👦 소개

🌱 문화

🔨 기술 스택

⚙️ 서비스 아키텍쳐

🚧 CI/CD

🌊 Flow

💭 6주를 보내면서

Clone this wiki locally