본문 바로가기
Front-End Study/코드잇 위클리 페이퍼

리액트 쿼리? 리액트가 이름 막 갖다 쓴다고 뭐라 안하나..

by 코딩기 2024. 7. 19.
728x90

리액트 쿼리는 왜 나왔고 왜 좋을까?

✨ 리액트 쿼리는 서버 상태 가져오기, 캐싱, 동기화 및 업데이트 를 기존의 코드보다 더욱 쉽고 간결하게 다룰 수 있도록 해준다.


📌 리액트 쿼리는 무슨 역할을 하나?

기존 상태 관리 라이브러리인 mobXredux는 클라이언트 상태 관리에 적합하나, 비동기 처리나 서버 상태 관리에는 미흡하다.

리액트 쿼리는 이런 기능이 있다!

  • 데이터 캐싱

  • 동일한 데이터에 대한 중복 요청을 단일 요청으로 통합

  • 백그라운드에서 오래된 데이터 업데이트

  • 데이터 업데이트를 가능한 빠르게 반영

  • 페이지네이션 및 데이터 지연 로드와 같은 성능 최적화

  • 서버 상태의 메모리 및 가비지 수집 관리

  • 구조 공유를 사용하여 쿼리 결과를 메모화

🙄 솔직히 요래 써놓으면 잘 감이 오지 않는다.

  • 간단히 말하자면, 서버와 클라이언트의 상태를 분리하여 편하게 관리하고, 다양한 옵션들을 선언적으로 간단하게 활용하는 것이 주 목적이다. (캐싱, 에러처리, 로딩 등)

📌 그럼 이 친구를 왜 사용하면 정확히 뭐가 좋은걸까??

1. 데이터 페칭의 단순화

  • 기존의 데이터 페칭은, 데이터를 가져올 페치 함수, 받아온 데이터를 넣어줄 상태값, 데이터를 가져오도록 유도할 사이드 이펙트 처리의 삼위일체를 통해 이루어졌다.

  • 이는 더할 나위없을 깔끔한 구조이나, 리액트 쿼리는 이를 더욱 단순화하여 하나의 코드만으로 이를 전부 처리할 수 있다..!

// 기존 코드
const [products, setProducts] = useState<listResponse[]>([]);

const handleLoad = async (orderQuery: OrderQuery) => {
    const { list } = await getProduct(orderQuery);
    setProducts(list);
  };

useEffect(() => {
  handleLoad({ orderBy, page, pageSize, keyword });
}, [orderBy, page, pageSize, keyword]);

// useQuery
const {data, isPending, isError} = useQuery({queryKey: ['userData', orderBy, page, pageSize, keyword], queryFn: getProduct(orderBy, page, pageSize, keyword)})

장점은 이 정도가 있겠다.

  • 코드 수 감소로 인한 Side Effect 제거
  • Data Fetching 방식 규격화

2. 캐싱

특정 데이터의 복사본을 저장하여 데이터가 변경되지 않았다면 이를 재사용해 효율성 및 재접근 속도를 증가시키는 것

  • gcTime의 기본값 5분, staleTime 기본값 0초를 가정
  1. A라는 queryKey를 가진 A 쿼리 인스턴스가 mount
  2. 네트워크에서 데이터 fetch하고, 불러온 데이터는 A라는 queryKey로 캐싱
  3. 이 데이터는 fresh상태에서 staleTime(기본값 0) 이후 stale 상태로 변경
  4. A 쿼리 인스턴스 unmount
  5. 캐시는 gcTime(기본값 5min) 만큼 유지되다가 가비지 콜렉터(GC)로 수집
  6. 만일, gcTime가 지나기 전이고, A 쿼리 인스턴스 fresh한 상태라면 새롭게 mount 되더라도 캐시 데이터 사용
  • 추가적으로 데이터 갱신 시점을 옵션으로 따로 지정하는 것도 가능

3. 클라이언트 데이터와 서버 데이터의 분리

const { data, isLoading } = useQueries(
  ["unique-key"],
  () => {
    return api({
      url: URL,
      method: "GET",
    });
  },
  {
    onSuccess: (data) => {
      // data로 이것저것 하는 로직
    },
  },
  {
    onError: (error) => {
      // error로 이것저것 하는 로직
    },
  }
);
  • 위 코드와 같이 onSuccess, onError 등을 통한 분기를 설정하여 페칭 성공, 실패 여부를 구분해 데이터 관리가 가능하다.

Client 데이터는 상태 관리 라이브러리가 관리하고, Server 데이터는 React-Query가 관리하는 구조를 통해 우리는 클라이언트 상태 데이터와 서버 상태 데이터를 온전하게 분리할 수 있다.


📌 그럼 클라이언트 상태와 서버 상태는 뭔데??

✨ 말 그대로 클라이언트와 서버 각각의 데이터가 관리되는 상태를 의미한다.

  • 클라이언트의 경우, 브라우저 내에서 관리되며 저장 또한 브라우저에 된다. 또한 새로고침 시 상태가 초기화 된다는 특징이 있다.

    • useState 와 같은 상태값을 통해 관리할 수 있으며 사용자 인터페이스를 다룬다.
  • 서버의 경우, 서버 자체에서 관리되는 데이터를 의미하며 API 호출을 통해 관리한다. 또한 새로고침 시에도 서버 자체의 데이터이므로 초기화되지 않는다.

    • React Query, SWR 등과 같은 라이브러리를 통해 개발자가 접근하여 관리할 수 있다.

✅ 따라서, 클라이언트 및 서버 상태를 동시에 신경써야 하는 개발자의 일을 좀 더 효율적으로 도와주는 것이 바로 React Query라고 할 수 있겠다.