[React] React Query[V5] 캐싱 눈으로 확인하기!

이원찬·2024년 5월 20일

React

목록 보기
8/17

react-query 를 첫 사용하면서 습득한 지식을 공유합니다.

리액트 쿼리를 사용하는 이유? 기능들!

1) 간편한 데이터 관리

데이터 가져오기, 캐싱, 동기화 및 업데이트 처리를 간편하게 할 수있게 해준다.

2) 실시간 업데이트 및 동기화

실시간 데이터 업데이트와 자동 동기화를 지원하여 서버와 클라이언트 데이터의 일관성 유지를 도와준다.

3) 데이터 캐싱

데이터를 캐싱하여 불필요한 API 요청을 줄이고 애플리케이션의 성능을 향상시킨다.

4) 서버 상태 관리

서버 상태 관리 (예를들면 로딩중, 에러, 성공 등의 상태)를 간편하게 처리 가능하다.

5) 간편한 설정

React Query는 간단한 설정으로 사용 가능하다.

설정하기 및 간단 사용법

  1. 설치하기

    npm install @tanstack/react-query @tanstack/react-query-devtools
  2. 세팅하기 (QueryClientProvider 로 감싸주기)

    최상위 컴포넌트를 QueryClientProvider 로 감싸주면된다. (App.js)

    const root = ReactDOM.createRoot(document.getElementById('root'));
    
    const queryClient = new QueryClient();
    
    root.render(
        <QueryClientProvider client={queryClient}>
            <ReactQueryDevtools /> {/* 선택 사항 이거 안넣으면 밑에 그림 안뜸 */}  
            <App/>
        </QueryClientProvider>
    );

    그러면 아래 예쁜 그림이 뜬다.

  3. 간단하게 useQuery 사용해보기

    이전 fetch나 axios를 이용한 코드

    const [, setData] = useState()
    
    const getNaverPage = async () => {
        let response = await axios.get("someurl");
        return response.data
    };
    
    useEffect(() => {
        getNaverPage().then((data) => {
            setData(data);
        })
    }, []);

    같은 역할을 하는 react_query 코드

    React Query v5부터 useQuery 훅은 하나의 객체 인수를 받는 방식으로 변경되었습니다

    import './App.css'
    import axios from "axios";
    import {useQuery} from "@tanstack/react-query";
    
    function App() {
        const getSomeData = async () => {
            return await axios.get("someurl");
        };
    
        let {
            data,
            isLoading
        } = useQuery({
            queryKey: ["some"],
            queryFn: getSomeData
        });
    
        return (
            <div>{isLoading ? "로딩중..." : JSON.stringify(data.data)}</div>
        )
    }
    
    export default App
    

    위 처럼 작성 하면 평소에 내가 사용하던 isFetching, isLoading 상태들을 리액트 쿼리가 알아서 해준다.

Query & Mutation

react query 에서 주용 사용되는 기능인 QueryMutation을 알아보자

react query에서는 API 요청을 위 두가지 형태로 처리한다.

  1. Query
  2. Mutation

Query

query 함수를 이용해 데이터를 가져오고 캐싱할수 있다.

보통 데이터 페칭용으로 사용되고

보통 GET으로 가져오는 코드에서 사용한다.

💡 공식문서에서는 서버에 데이터를 수정하는 코드라면 Mutation을 권장한다!

const { data,isLoading,isFetching,... } = useQuery(
	queryKey,
	queryFunction,
	options,
)

인자 설명

  • 첫번째 인자 데이터를 캐싱할 키값이다. 캐싱을 위해 키값을 유니크 하게 관리하는것이 중요하다.
  • 두번째 인자 query Function 으로 Promise를 반환하는 함수이다. fetch 또는 axios를 이용한 함수를 의미한다.
  • 세번째 인자 useQuery에 사용되는 옵션을 지정하는 객체이다.
  • 자주 사용되는 리턴값
    • isLoading : 데이터를 가져오는 중인지 알려주는 상태 boolean 변수

    • isFetching : 위와 동일

    • error : 에러가 발생했을때 반환되는 객체

      위 리턴값들 이외에 다양한 리턴값들이 많다 기능이 궁금하다면 공식문서를 확인하자

      useQuery | TanStack Query React Docs

Mutaion

보통 데이터를 업데이트하고 캐시를 업데이트 할 사용한다.

보통 데이터 생성, 수정, 삭제 용으로 사용되며 POST, PUT, DELETE 요청시에 사용합니다.

아래는 서버에 새 할일 (todo)를 생성하는 예제 코드이다.

const getSomeData = async (newTodo) => {
        return await axios.post("http://127.0.0.1:3000", {할일: newTodo});
    };

    let {mutate, data, isPending, isIdle} = useMutation({
        mutationFn: getSomeData,
        onSuccess: (data, variables, context) => {},
        onMutate: (variables) => {}
    })

    const [input, setInput] = useState("")

    return (
        <>
            <input type="text" onChange={(e) => {
                setInput(e.target.value)
            }} value={input}/>
            <button onClick={() => {
                mutate(input);
            }}>보내기
            </button>
            {!isIdle && <div>{isPending ? "보내는중..." : JSON.stringify(data.data)}</div>}
        </>
    )

mutation 은 자동으로 실행되지 않기 때문에 click이나 submit 으로 호출해줘야 한다.

useMutation 안 옵션들

  • onMutate

    mutate 가 발생하기 전 실행되는 함수!

    인자값 : variablesmutationFn 에 전해진 변수이다.

    반환값: 컨텍스트(context) 객체를 반환하여 나중에 onError, onSuccess, onSettled 콜백에서 사용할 수 있다.

  • onSuccess

    mutate 가 성공했을때 실행되는 콜백

    인자값 :

    1. mutationFn 가 반환한 : data
    2. mutationFn가 넘겨받은 인자 : variales
    3. onMutate에서 반환된 객체 : context
  • onSettled

    mutate가 성공 또는 실패 했을때 실행되는 콜백!

    무조건 onSuccess가 먼저 실행되는 특징이 있음!

더 많은 정보는 공식문서 에서…

Mutations | TanStack Query React Docs

React Query의 데이터 캐싱 (캐싱 직접 확인해보기)

staletime, gcTime 옵션을 사용하면 데이터 캐싱 기능을 이용할 수 있다.

staletime (데이터 신선도 기준 시간)

갱신 지연 시간으로 신선한 데이터 기준 시간 설정이다

만약 5분으로 설정했다면 처음 가져오고 5분동안은 가져오지 않고 5분이 지나서야 새로운 데이터를 가져온다.

기본적으로 0 으로 설정되어 있어 한번 가져오면 만료되고 계속 다시 가져온다.

5초로 설정한 화면

// 간단한 버튼을 눌렀다 떼면 ShowData 컴포넌트가 마운트, 언마운트 되는 App.js 파일이다.
<button onClick={() => {
    setIsClick(!isClick)
}}>click
</button>
{isClick && <ShowData/>}
//ShowData 컴포넌트
const ShowData = () => {
    const getData = async () => {
        return await axios.get("http://127.0.0.1:3000")
    };

    let {data: someData, isFetching, status} = useQuery({
        queryKey: ["some"],
        queryFn: getData,
        staleTime: 1000 * 5,
    })

    return (
        <div>가져온 데이터
            : {isFetching && "가져오는중"}{!isFetching && status === "success" && JSON.stringify(someData.data)}</div>
    )
};

stale 되자마자 리렌더링시 다시 데이터를 가져오는 모습

gcTime (가비지 컬렉터 시간 : (구)cacheTime)

gcTime 시간동안 캐시데이터가 사용되지 않았다면 캐시를 삭제 한다

staletime 를 1시간으로 설정한뒤 gcTime 를 1초로 설정한다면 어떻게 될까?

ShowData 컴포넌트는 위와 같다.
...
//ShowData 컴포넌트
const ShowData = () => {
    const getData = async () => {
        return await axios.get("http://127.0.0.1:3000")
    };

    let {data: someData, isFetching, status} = useQuery({
        queryKey: ["some"],
        queryFn: getData,
        staleTime: 1000 * 60 * 60,
        gcTime: 1000
    })

    return (
        <div>가져온 데이터
            : {isFetching && "가져오는중"}{!isFetching && status === "success" && JSON.stringify(someData.data)}</div>
    )
};

언마운트 된지 1초도 안됬을때는 캐시데이터를 잘 사용하다가 언마운트된지 1초가 넘자 캐시에서 데이터가 사라지는 모습이다.

참고 자료
React-query 를 사용해 상태관리를 해보자
https://tanstack.com/

profile
소통과 기록이 무기(Weapon)인 개발자

0개의 댓글