QueenCards / ProjectAnalysis

플젝뿌셔
1 stars 0 forks source link

[14] ReactQuery를 왜 썼나요? 이점이 뭔가요? next.js를 채택했다면 사용하지 않을 수도 있지 않나요? #16

Closed hyeyoonS closed 2 months ago

hyeyoonS commented 2 months ago

📎 질문

ReactQuery를 왜 썼나요? 이점이 뭔가요? next.js를 채택했다면 사용하지 않을 수도 있지 않나요?

✏ 구술 답변 키워드

✏ 서술 답변

reactQuery란

추가 ) reactQuery의 사용방법([react-query 개념 및 정리](https://kyounghwan01.github.io/blog/React/react-query/basic/#usequeries)) * useQuery : get API * unique key, api호출함수를 인자로 가짐. ```tsx const Todos = () => { const { isLoading, isError, data, error } = useQuery("todos", fetchTodoList, { refetchOnWindowFocus: false, retry: 0, onSuccess: data => { // 성공시 호출 console.log(data); }, onError: e => { // 실패시 호출 (401, 404 같은 error가 아니라 정말 api 호출이 실패한 경우만 호출.) console.log(e.message); } }); // isLoading, isError를 따로 받지 않고, status 하나만 받아도 처리 가능 // ex) if(status === "loading") if (isLoading) { return Loading...; } if (isError) { return Error: {error.message}; } return (
    {data.map(todo => (
  • {todo.title}
  • ))}
); }; ``` * useQuery 동기적 실행 : enabled 옵션으로 ```tsx const { data: todoList, error, isFetching } = useQuery("todos", fetchTodoList); const { data: nextTodo, error, isFetching } = useQuery( "nextTodos", fetchNextTodoList, { enabled: !!todoList // true가 되면 fetchNextTodoList를 실행한다 } ); ``` * useQueries : 여러 비동기 호출을 하는 경우 ```tsx // 아래 예시는 롤 룬과, 스펠을 받아오는 예시. // queries 안에 배열로 넣어주면 된다. const result = useQueries([ { queryKey: ["getRune", riot.version], queryFn: () => api.getRunInfo(riot.version) }, { queryKey: ["getSpell", riot.version], queryFn: () => api.getSpellInfo(riot.version) } ]); useEffect(() => { console.log(result); // [{rune 정보, data: [], isSucces: true ...}, {spell 정보, data: [], isSucces: true ...}] const loadingFinishAll = result.some(result => result.isLoading); console.log(loadingFinishAll); // loadingFinishAll이 false이면 최종 완료 }, [result]); ``` * QueryCache : 쿼리에 대한 성공, 실패 전처리 ```tsx const queryClient = new QueryClient({ queryCache: new QueryCache({ onError: (error, query) => { console.log(error, query); if (query.state.data !== undefined) { toast.error(`에러 : ${error.message}`); }, }, onSuccess: data => { console.log(data) } }) }); ``` * useMutation : post, update API ```tsx import { useState, useContext, useEffect } from "react"; import loginApi from "api"; import { useMutation } from "react-query"; const Index = () => { const [id, setId] = useState(""); const [password, setPassword] = useState(""); const loginMutation = useMutation(loginApi, { onMutate: variable => { console.log("onMutate", variable); // variable : {loginId: 'xxx', password; 'xxx'} }, onError: (error, variable, context) => { // error }, onSuccess: (data, variables, context) => { console.log("success", data, variables, context); }, onSettled: () => { console.log("end"); } }); const handleSubmit = () => { loginMutation.mutate({ loginId: id, password }); }; return (
{loginMutation.isSuccess ? "success" : "pending"} {loginMutation.isError ? "error" : "pending"} setId(e.target.value)} /> setPassword(e.target.value)} />
); }; export default Index; ``` * update후 get다시 실행 : useMutation - invalidateQueries ```tsx const mutation = useMutation(postTodo, { onSuccess: () => { // postTodo가 성공하면 todos로 맵핑된 useQuery api 함수를 실행합니다. queryClient.invalidateQueries("todos"); } }); ```
Nahyun-Kang commented 2 months ago

리액트 쿼리

리액트 쿼리가 하는 일!

Jyophie commented 2 months ago

Next.js 프로젝트에서 React-query가 필요할까?

Next.js는 서버 사이드 렌더링(SSR)과 정적 사이트 생성(SSG) 지원을 통해 검색 엔진 최적화(SEO)에 유리한 환경과 초기 페이지 로딩 성능을 향상시켜준다. 이를 통해 우수한 사용자 경험을 제공할 수 있고, 앱 라우터 방식에서는 내장 fetch 함수를 페이지에서 비동기로 사용해 서버 사이드 렌더링을 구현하고 서버 액션을 가능하게 한다.

그렇다면 서버 상태 관리를 위한 React-query를 굳이 사용할 필요가 있을까? Next.js의 기본 제공 기능들이 매우 강력하기는 하지만, 모든 경우에 최적의 해결책을 제공하는 것은 아니다. 특히, 서버 상태 관리와 관련하여, React-query는 다음과 같은 몇 가지 이점을 제공한다.

이러한 이점을 고려할 때, React-query는 서버 상태를 관리하는 데 있어서 뛰어난 선택이 될 수 있다. 특히 대규모 프로젝트나 복잡한 데이터 흐름이 있는 애플리케이션에서 그 가치가 더욱 빛을 발한다. 결국, 사용하는 기술은 프로젝트의 요구사항과 팀의 선호도에 따라 달라질 수 있으며, Next.js와 React-query를 함께 사용함으로써 얻을 수 있는 시너지를 고려하는 것이 중요하다.

Eugene-A-01 commented 2 months ago

Q. ReactQuery를 왜 썼나요? 이점이 뭔가요? 서버에서 받아오는 데이터를 쉽게 관리하기 위해 사용했다. 리액트 쿼리를 이용하면 데이터의 fetching, caching, 요청 중복 제거, 서버데이터 동기화, 상태 등을 쉽게 파악하고 이용할 수 있었다. 리액트 쿼리의 이점으로는 효율적인 캐싱, 오래된 데이터 백그라운드 자동 업데이트, 페이징 처리와 로딩 지연 처리, 가비지컬렉션을 이용한 서버데이터 메모리관리, 중복요청 제거 가 있다.

Q. next.js를 채택했다면 사용하지 않을 수도 있지 않나요? Next.js 역시 SSR과 서버 데이터를 가져오는 기능을 내장하고 있지만, React Query를 이용하면 더 간단한 코드로 데이터를 관리할 수 있다. 데이터 fetching 뿐만 아니라 캐싱, 에러처리, 중복요청 제거, 무한스크롤 구현 등을 Next.js만 사용했을때보다 훨씬 짧은 코드로 별도의 설정없이 즉시 사용가능하다.

(next.js도 fetch함수로 캐싱 자체는 가능함 주의) fetch('https://...', { cache: 'force-cache' })

hyeyoonS commented 2 months ago

next.js는 내장 fetch함수를 제공하고 fetch로 캐시를 관리할 수 있습니다. 하지만 next.js에서 제공하는 fetch 만으로는 아직 next의 cache를 관리하는 게 어렵다는 의견을 보았습니다.

공식적으로 Next14는 캐시된 값을 버리는(invalidate) 기술을 두 가지 지원해 주는데,

  1. server cache invalidate

    • fetch('path', { cache: 'no-store' } 로 항상 새로운 데이터를 받아올 수 있습니다.
    • fetch('path', { tags: ['data'] }) 로 캐시를 특정할 수 있는 태그를 붙일 수 있습니다.
    • revalidatePath, revalidateTag 함수로 fetch + GET method 의 결과값을 invalidate 할 수 있습니다.
  2. client cache invalidate

    • router.refresh() : RQ에서 해당 페이지의 모든 쿼리를 invalidate하는 방식과 비슷합니다.클라이언트 렌더링 결과물만 바뀝니다. 캐시를 무효화하는 것이 아니라 페이지를 완전히 새로 로드하는 것이므로, 서버에서 새로운 HTML 페이지를 받아와서 클라이언트에게 다시 그리는 것과 유사합니다.

이 두 가지 방식을 조합해서 써야 하는데, client cache와 server cache를 생각하면서 잘 써야 하기 때문에 휴먼 에러가 다수 발생할 수 있습니다.

예시로,

사용자가 게시글을 수정하면 → 검색 페이지의 검색 결과에서도 해당 게시글 내용이 수정되어야 하는 경우에,

/search 에서 fetch('/getPost', { tags: [search] }) 로 데이터를 받고 (서버)

/post/edit경로에서 revalidateTag('search') 로 서버의 캐시를 invalidate (서버)

하지만 클라이언트 컴포넌트에서 router.refresh() 를 사용해도 수정 사항이 반영되지 않습니다. 서버의 캐시만을 지웠을 뿐이기 때문입니다.….. 서버에서 최신 데이터를 다시 가져온 후 router.refresh()로 화면을 새로 그리거나 or state를 사용하여 데이터를 mutate하여야 합니다.

//state를 사용하여 데이터를 mutate하는 예시코드
import React, { useState } from 'react';

function PostComponent() {
  const [postData, setPostData] = useState(null);

  // 게시글 데이터를 업데이트하는 함수
  const updatePostData = (newData) => {
    setPostData(newData);
  };

  return (
    <div>
      <p>{postData}</p>
    </div>
  );
}

따라서 next.js에서 제공하는 fetch함수를 사용할 경우 서버와 클라이언트의 캐시를 각각 고려해야 하고, 코드가 매우 복잡해지기에 Client Component에서 데이터 Fetching 을 하는 경우 RQ를 쓰는 게 더 편하다는 의견을 따랐습니다.

++ 또한 관련하여 학습을 할 때에 revalidate 함수를 사용한 경로에서 해당 경로의 client cache가 모두 날아가서, 화면 전체 렌더링이 되는 이슈가 있었습니다. 임시적인 것으로 차기 버전에서는 수정 될 것이라고 합니다.

HaydenDevK commented 2 months ago

React Query란

next.js를 사용한다면 React Query가 굳이 필요할까?