비동기 통신 - axios, fetch

최재홍·2023년 4월 27일
0
post-custom-banner

비동기 통신의 대표적인 방법은 axios와 fetch가 있다.

axios

공식문서에 따르면 axios란 node.js와 브라우저를 위한 promise 기반 http 클라이언트라고 소개한다. 다시 말해 http를 이용해서 서버와 통신하기 위해 사용하는 패키지라고 생각하면 된다.

axios 설치

yarn add axios

axios - GET

get은 서버의 데이터를 조회할 때 사용한다.

// url에는 서버의 url이 들어가고, config에는 기타 여러가지 설정을 추가할 수 있습니다.
// config는 axios 공식문서에서 확인하세요.

axios.get(url[, config]) // GET

API 명세서 확인하기의 중요성

기본적으로 GET요청을 할 때, path variable로 해야할지, query로 보내야할지는 API를 만든 사람이 하라는대로 해야 한다.

보다시피 실습으로 활용한 json-server는 공식문서를 보면, 전체 정보다 상세 정보는 path variable로 url을 작성하도록 되어있고, filter와 같은 기능을 위해서 GET요청을 하고자 할 때는 query로 보내라고 명시하고 있다.

axios - POST

axios.post(url[, data[, config]])   // POST

post는 보통 서버에 데이터를 추가할 때 사용한다. 다만 post 요청에 대한 로직은 BE 개발자가 구현하는 것이기 때문에 추가외에 다른 용도로 사용될 수 있다. 하지만 보통은 클라이언트의 데이터를 body 형태로 서버에 보내고자 할 때 사용한다.

axios - DELETE

delete는 저장되어 있는 데이터를 삭제하고자 요청을 보낼 때 사용한다.

axios.delete(url[, config])  // DELETE

axios - PATCH

axios.patch(url[, data[, config]])  // PATCH

patch는 보통 어떤 데이터를 수정하고자 서버에 요청을 보낼 때 사용하는 메서드이다.


ex)

// src/App.js

import React, { useEffect, useState } from "react";
import axios from "axios"; 

const App = () => {
  const [todo, setTodo] = useState({
    title: "",
  });

  const [todos, setTodos] = useState(null);

  const fetchTodos = async () => {
    const { data } = await axios.get("http://localhost:3001/todos");
    setTodos(data); 
  };

  const onSubmitHandler = (todo) => {
    axios.post("http://localhost:3001/todos", todo);
  };

	// 새롭게 추가한 삭제 버튼 이벤트 핸들러 
  const onClickDeleteButtonHandler = (todoId) => {
    axios.delete(`http://localhost:3001/todos/${todoId}`);
  };

  useEffect(() => {
    fetchTodos();
  }, []);

  return (
    <>
      <form
        onSubmit={(e) => {
          e.preventDefault();
          onSubmitHandler(todo);
        }}
      >
        <input
          type="text"
          onChange={(ev) => {
            const { value } = ev.target;
            setTodo({
              ...todo,
              title: value,
            });
          }}
        />
        <button>추가하기</button>
      </form>
      <div>
        {todos?.map((todo) => (
          <div key={todo.id}>
            {todo.title}
            {/*  디자인이 요상하긴 하지만..! 삭제 버튼 추가 */}
            <button
              type="button"
              onClick={() => onClickDeleteButtonHandler(todo.id)}
            >
              삭제하기
            </button>
          </div>
        ))}
      </div>
    </>
  );
};

export default App;

Fetch

axios가 npm명령어나 yarn명령어로 설치를 해야만 하는 패키지였다면, fetch는 자바스크립트에서 자체적으로 제공하는 내장 라이브러리이다. 따라서 별도의 설치나 import를 필요로 하지 않는다.

앞으로 axios위주로 사용하게 될텐데 그건 fetch가 가진 몇가지 단점들 때문이다.

  • 미지원 브라우저 존재
  • 개발자에게 불친절한 response
  • axios에 비해 부족한 기능

예시로 보는 fetch와 axios의 차이점

데이터 읽어오기

  1. fetch
const url = "https://jsonplaceholder.typicode.com/todos";

fetch(url)
.then((response) => response.json())
.then(console.log);
  • fetch().then을 한 상태여도 여전히 JSON 포맷의 응답이 아니기 때문에 response.json()을 한번 더 해주는 과정이 필요하다.
  • 따라서, fetch로 데이터를 요청하는 경우 두 개의 .then()이 필요하다.
  1. axios
const url = "https://jsonplaceholder.typicode.com/todos";

axios.get(url).then((response) => console.log(response.data));
  • axios는 친절하게도 응답(response)을 기본적으로 JSON 포맷으로 제공한다. 우리는 단순히 response.data로만 사용하면 된다.

에러 처리

  1. axios
const url = "https://jsonplaceholder.typicode.com/todos";

axios
  .get(url)
  .then((response) => console.log(response.data))
  .catch((err) => {
    console.log(err.message);
  });
  • axios.get()요청이 반환하는 Promise 객체가 갖고있는 상태코드가 2xx의 범위를 넘어가면 거부(reject)를 한다.
  • 따라서, 곧바로 catch() 부분을 통해 error handling이 가능하다. 예를들면 이렇게.
const url = "https://jsonplaceholder.typicode.com/todos";

// axios 요청 로직
axios
  .get(url)
  .then((response) => console.log(response.data))
	.catch((err) => {

		// 오류 객체 내의 response가 존재한다 = 서버가 오류 응답을 주었다	
		if (err.response) {
			
	    const { status, config } = err.response;
	
			// 없는 페이지
	    if (status === 404) {
	      console.log(`${config.url} not found`);
	    }

			// 서버 오류
	    if (status === 500) {
	      console.log("Server error");
	    }
	
		// 요청이 이루어졌으나 서버에서 응답이 없었을 경우
	  } else if (err.request) {
	    console.log("Error", err.message);
		// 그 외 다른 에러
	  } else {
	    console.log("Error", err.message);
	  }
	});
  1. fetch
const url = "https://jsonplaceholder.typicode.com/todos";

fetch(url)
  .then((response) => {
    if (!response.ok) {
      throw new Error(
        `This is an HTTP error: The status is ${response.status}`
      );
    }
    return response.json();
  })
  .then(console.log)
  .catch((err) => {
    console.log(err.message);
  });

fetch의 경우, catch()가 발생하는 경우는 오직 네트워크 장애 케이스이다. 따라서 개발자가 일일히 then() 안에 모든 케이스에 대한 HTTP 에러 처리를 해야 한다.

post-custom-banner

0개의 댓글