본문 바로가기
REACT

[React] 272샘의 React15 ( restful, tanstack, axios )

by 미눅스[멘토] 2024. 10. 31.
728x90

 

 

 

 

https://deahan.tistory.com/442

 

[React] 272샘의 React14 ( useEffect Hook + fetc )

https://deahan.tistory.com/433 [React] 272샘의 React13 ( useEffect Hook )https://deahan.tistory.com/432 [React] 272샘의 React12 ( useRef Hook )https://deahan.tistory.com/431 [React] 272샘의 React11 ( useState Hook )https://deahan.tistory.com/430 

deahan.tistory.com

글에서 우리가 설치한   json-server는  눈치 못챘겠지만  Restful 서버다
Restful이란 url이 아닌 클라이언트로 부터 온 메소드가 무엇인가? 에 따라
서버 동작이 결정되는 것인데, 강제는 아니고 써보니  명확하고 좋아서 모두 그렇게 쓰는
관례다. 규모가 커졌을 때 프론트 와 백엔드를 나누어 작업할 때도 그렇게 좋다.


아래가 가장 일반적 메소드 사용 관례다.(참고로 form태그는 get과 post만 지원한다)
모두 지원하는 것은 AJAX다 (아래 이외에도 patch등등 더 있다.)

GET 은 조회, POST는 생성, PUT은 수정, DELETE는 삭제 

 

json-server가 restful임을 확인하기 위해  chrome web store에서 rest client로 검색
아래 boomerang을 브라우져 확장 프로그램으로 추가하자.
(그냥 브라우져에선  코드 작성없이 get 이외의 메소드 요청을 할 수 없어서 필요하다)

 

사실 추천하고 싶은 건 Talend API Tester - Free Edition 인데..
여기선 Boomerang이 큼직큼직 해서 지금 상황에선 더 적합하다.
Boomerang을 이용하여 json-server가 restful임을 확인하자.
먼저 get 메소드 전체 리스트

 

get 메소드 특정 id 한명만 조회 

 

 

post 메소드 생성 (데이터 추가)

생성 후에 메소드만 POST에서 GET으로 바꾸어 보면 추가 된 걸 확인 가능


put 메소드 수정 (데이타 변경)

수정 후에 메소드만 PUT에서 GET으로 바꾸어 보면 추가 된 걸 확인 가능  

 

DELETE는 직접 한번 해보기 바람

 

지난 글에서 우세종이라 이야기 했던 것이  react-query인데, 지금은 더 유명해져서

tanstack이라고 불리고, 물 들어올 때 노 저으라고 마구 인기 상승중이다.

 

낯설긴 하겠지만 요 타이밍에 얼굴이라도 익히게 한번 써먹어 보자.(자주 봐야 친해진다.)

비동기도 지난번엔 fetch를 썼으니, 이번엔 axios를 한번 써보자.(then을 한번만 쓰면 되서 좋다!)

styled-components 는 기억이 안난다면 기억해라...?

D:\reactstudy\rfetchaxios>npm install @tanstack/react-query
D:\reactstudy\rfetchaxios>npm install axios
D:\reactWS\rfetchaxios>npm install styled-components

 

react-query를 쓰기 위해선 App.jsx에 아래와 같은 세팅이 필요하다.

처음에만 낯설당.  react엔 이런 스타일의 설정이 꽤 된당. 일단 눈 여겨 보자.

 

App.jsx

 
import "./App.css";
import Container from "./Container";
import { QueryClientProvider, QueryClient } from "@tanstack/react-query";

const queryClient = new QueryClient();

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <div>
        <Container />
      </div>
    </QueryClientProvider>
  );
}

export default App;
 
 

 

 

Container.jsx  아래와 같이 하자

 
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
import "./Container.css";
import Friend from "./Friend";

function Container() {
  const { isPending, isError, data } = useQuery({
    queryKey: ["getFriends"],
    queryFn: async () => {
      const res = await axios.get("http://localhost:8272/friends");
      return res.data;
    },
  });

  console.log("체크", data);
  if (isPending) return <h4>아직 로딩중</h4>;
  if (isError) return <h4>에러</h4>;

  return (
    <div className="container">
      <h1>경미니 베.푸(Very Proud)들</h1>
      {data?.map((friend) => (
        <Friend
          key={friend.id}
          fid={friend.id}
          name={friend.name}
          age={friend.age}
          avatar={friend.avatar}
          job={friend.job}
        />
      ))}
      <div className="minux">&copy;MINUX 만만세</div>
    </div>
  );
}

export default Container;
 

 

결과는 이전 글과 같지 않을 수 없다!!.
상세 설명을 하기 전에 오늘은 Container function안의 흐름만 눈여겨 보길 바란다.
useQuery 이후로 그저 아래로 비동기식 흐름이 아니라, 동기식 흐름에,
useState도 없다.  이거이 react-query의 장점이다. 그저 아래로 눈이 흐르면 된다.
(....??? 아마 아직 아닐거다...  몇번은 더 봐야 할것이다.)
이왕 본 김에 조금 더 나아가 보자

 


MyButton.jsx 

 
import styled from "styled-components";

const MyButton = styled.button`
  color: #fff;
  background-color: #0069d9;
  border-color: #0062cc;
  border-radius: 8px;
  margin-right: 10px;
  width: 200px;
  height:50px;
  font-size:1.5em;
`;

export default MyButton;
 

 

 

Container.jsx   조금 길고 낯설겠지만 그냥 흐름 style을 편한 맘으로 인사정도로 보자

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { faker } from "@faker-js/faker/locale/ko";
import axios from "axios";
import "./Container.css";
import Friend from "./Friend";
import MyButton from "./MyButton";

function Container() {

  //친구 추가 함수
  const handleAdd = ()=>{
    alert("친구 추강");
    const friend = {
      "id": `f${faker.number.int({ min: 13, max: 999 })}`,
      "name": faker.person.firstName(),
      "age": faker.number.int({min: 22, max: 55 }),
      "avatar": faker.person.firstName(),
      "job":  faker.person.jobTitle().split(" ")[1]
    }
    // mutation 호출
    insertMutate.mutate(friend);
  }

  // 친구 삭제 함수
  const handleRemove = ()=>{
    alert("친구 삭제");
    if(!data.length) return;
    const fid = data[0].id;
    // mutation 호출
    deleteMutate.mutate(fid);
  }

  // App.js에서 만든 queryClient 접근
  const queryClient = useQueryClient();

  // 조회시 useQuery 사용, 곧 get방식
  const { isPending, isError, data } = useQuery({
    queryKey: ["getFriends"],
    queryFn: async () => {
      const res = await axios.get("http://localhost:8220/friends");
      return res.data.sort((a,b)=> {
         if( a.id > b.id) return -1;
         else return 1;
      });
    },
  });

  // 추가, 수정, 삭제는 mutation 사용, 여긴 추가 mutation
  const insertMutate = useMutation({
    mutationFn: friend =>{
       axios.post("http://localhost:8220/friends",friend)
    },
    onSuccess:()=>{
      alert("추가 성공");
      queryClient.invalidateQueries(["getFriends"])
    }
  })

  // 삭제 mutation
  const deleteMutate = useMutation({
    mutationFn: fid =>{
       axios.delete(`http://localhost:8220/friends/${fid}`)
    },
    onSuccess:()=>{
      alert("삭제 성공");
      queryClient.invalidateQueries(["getFriends"])
    }
  })


  console.log("체크", data);
  if (isPending) return <h4>아직 로딩중</h4>;
  if (isError) return <h4>에러</h4>;

  return (
    <div className="container">
      <MyButton onClick={handleAdd}>친구 추강</MyButton>
      <MyButton onClick={handleRemove}>친구 삭제</MyButton>
      <h1>경미니 베.푸(Very Proud)들</h1>
      {data?.map((friend) => (
        <Friend
          key={friend.id}
          fid={friend.id}
          name={friend.name}
          age={friend.age}
          avatar={friend.avatar}
          job={friend.job}
        />
      ))}
      <div className="minux">&copy;MINUX 만만세</div>
    </div>
  );
}

export default Container;

 

브라우져가 내 눈앞에 아래 화면을 드리 밀었다~~. 꽤나 잘 된다.

react-query는 사실 단순하다. get방식(조회)에 useQuery,

post/put/delete 방식(추가/수정/삭제)에는 useMutation을  사용법만 낯설것이다.

 

data?.map 표현은 Optional Chaining(선택적 체인닝) 이라 불리는 데, 처음 본다면 참 재밌다. 

 

react-query는 많이 써야 하니, 여유롭게 천천히  친해져 보도록 하자.

 

 

 

 

 

출처 : https://e-7-e.tistory.com/263