React Native로 앱을 만들다 보면 외부 API에서 데이터를 가져오거나 서버에 데이터를 저장하는 일이 자주 발생합니다. 이때 단순히
fetch
함수만 사용하면, 로딩 상태나 오류 처리, 캐싱 등 여러 번 반복되는 패턴을 매번 직접 구현해야 해서 번거롭습니다.
이를 해결하기 위해
TanStack Query
를 사용하면 데이터 패칭을 매우 간편하고 안정적으로 처리할 수 있습니다. 이 글에서는 React Native (Expo) 환경에서 TanStack Query를 설치하고 활용하는 방법을 기초부터 차근차근 예제와 함께 안내해 드리겠습니다.
🚀
TanStack Query란 무엇인가요? 🔗
TanStack Query는 서버에서 가져오는 데이터를 효율적으로 관리할 수 있도록 도와주는 상태 관리 라이브러리입니다. 예전 이름은 React Query였으며, 현재는 다양한 플랫폼을 지원하는 범용 도구로 발전했습니다.
React Native에서도 다음과 같은 상황에서 유용하게 사용할 수 있습니다:
서버에서 받아온 데이터를 캐시하고, 동일한 요청을 중복하지 않도록 할 때
네트워크 연결 상태나 앱 포커스에 따라 데이터를 자동으로 다시 불러올 때
에러나 로딩 상태를 자동으로 처리하고 싶을 때
React Native (Expo) 프로젝트에서 TanStack Query를 사용하려면 다음과 같이 설치합니다:
npx expo install @tanstack/react-query
npm i -D @tanstack/eslint-plugin-query
🚀
QueryClientProvider 설정하기 🔗
설치를 마쳤다면 QueryClient
를 만들고, 앱의 최상단 컴포넌트를 QueryClientProvider
로 감싸야 합니다.
import { QueryClient, QueryClientProvider } from '@tanstack/react-query' ;
const queryClient = new QueryClient ();
export default function App () {
return (
< QueryClientProvider client ={ queryClient } >
{ /* 앱 컴포넌트들 */ }
</ QueryClientProvider >
);
}
이렇게 설정하면 이제부터 앱 전체에서 TanStack Query 기능을 사용할 수 있게 됩니다.
이제 가장 기본적인 사용법부터 살펴보겠습니다. JSONPlaceholder의 사용자 API(/users
)를 가져와서 리스트로 표시해보겠습니다.
import { useQuery } from '@tanstack/react-query' ;
import axios from 'axios' ;
import { FlatList, Text, View } from 'react-native' ;
const fetchUsers = async () => { // 정보를 fetch하는 함수
const res = await axios. get ( 'https://jsonplaceholder.typicode.com/users' );
return res.data;
};
export default function UserList () {
const { data , isLoading , isError , error } = useQuery ({
queryKey: [ 'users' ], // 쿼리의 고유 식별자
queryFn: fetchUsers, // 정보를 fetch하는 함수
});
if (isLoading) return < Text >불러오는 중...</ Text >;
if (isError) return < Text >오류 발생: { (error as Error ).message } </ Text >;
return (
< FlatList
data ={ data }
keyExtractor ={ ( item ) => item.id. toString () }
renderItem ={ ({ item }) => < Text > { item.name } </ Text > }
/>
);
}
queryKey
는 요청을 구분하고 캐시를 적용하는 데 매우 중요한 역할을 합니다. 배열 형태로 작성하며, 특정 파라미터에 따라 다르게 구성할 수 있습니다.
useQuery ({
queryKey: [ 'user' , userId],
queryFn : () => fetchUser (userId),
});
여기서 userId
가 다르면 다른 쿼리로 인식되어 각기 다른 캐시를 사용하게 됩니다.
앱이 포커스를 얻을 때 자동으로 쿼리를 다시 실행하고 싶다면 AppState
와 focusManager
를 사용합니다:
import { useEffect } from 'react' ;
import { AppState, Platform } from 'react-native' ;
import { focusManager } from '@tanstack/react-query' ;
function onAppStateChange ( status ) {
if (Platform. OS !== 'web' ) {
focusManager. setFocused (status === 'active' );
}
}
useEffect (() => {
const subscription = AppState. addEventListener ( 'change' , onAppStateChange);
return () => subscription. remove ();
}, []);
🚀
React Navigation과 화면 포커스 시 refetch 🔗
React Navigation에서는 useFocusEffect
를 활용하여 화면에 들어올 때 데이터를 갱신할 수 있습니다:
import { useFocusEffect } from '@react-navigation/native' ;
import { useCallback } from 'react' ;
export function useRefreshOnFocus ( refetch ) {
useFocusEffect (
useCallback (() => {
refetch ();
}, [])
);
}
서버에 데이터를 등록하거나 수정할 때는 useMutation
을 사용합니다. 아래는 게시글을 추가하는 예시입니다:
import { useMutation, useQueryClient } from '@tanstack/react-query' ;
import axios from 'axios' ;
const createPost = async ( newPost ) => {
const res = await axios. post ( 'https://jsonplaceholder.typicode.com/posts' , newPost);
return res.data;
};
export function NewPostButton () {
const queryClient = useQueryClient (); // 쿼리 클라이언트 인스턴스
const mutation = useMutation ({
mutationFn: createPost, // 뮤테이션 함수
onSuccess : () => {
queryClient. invalidateQueries ({ queryKey: [ 'posts' ] }); // 쿼리 데이터 무효화
},
});
return (
< Button
title = "새 글 작성"
onPress ={ () => mutation. mutate ({ title: '제목' , body: '내용' }) } // 뮤테이션 실행
/>
);
}
🚀
React Native에서 Devtools 사용 🔗
웹과는 달리 React Native에서는 Devtools를 바로 사용할 수는 없습니다. 다음과 같은 도구를 통해 쿼리 상태를 확인할 수 있습니다:
다음 명령어로 플러그인을 설치합니다.
npx expo install @dev-plugins/react-query
플러그인을 사용하려면 다음과 같이 설정해야 합니다.
import { QueryClient, QueryClientProvider } from '@tanstack/react-query' ;
import { useReactQueryDevTools } from '@dev-plugins/react-query' ;
const queryClient = new QueryClient ({});
export default function App () {
useReactQueryDevTools (queryClient); // 디버깅 도구 초기화
return (
< QueryClientProvider client ={ queryClient } >
{ /* ... */ }
</ QueryClientProvider >
);
}
이제 앱을 실행한 터미널에서 shift + M 키를 눌러 Open @dev-plugins/react-query
를 선택하면 웹 브라우저에서 디버깅 도구를 열 수 있습니다.
React Native (Expo)에서 TanStack Query를 사용하면 데이터 패칭, 캐싱, 에러 처리, 상태 관리 등을 매우 간단하고 효율적으로 구현할 수 있습니다. 특히 모바일 환경에서는 네트워크 연결 상태나 앱 포커스에 따라 데이터 동기화를 자동으로 처리하는 기능이 매우 유용합니다.
이번 포스팅을 통해 기초부터 실전 사용까지 예제와 함께 익히셨기를 바랍니다.