# React Native와 GraphQL 2026: Apollo Client, 쿼리 및 면접 질문 > Apollo Client 4.0을 사용하여 React Native에 GraphQL을 통합하는 방법을 알아봅니다. 쿼리, 뮤테이션, 캐싱 전략, 모바일 GraphQL 개발 면접 질문을 다룹니다. - Published: 2026-08-20 - Updated: 2026-08-20 - Author: Anthony Fillion-Maillet - Tags: react-native, graphql, apollo-client, mobile, api, interview - Reading time: 9 min --- GraphQL은 유연한 데이터 페칭과 효율적인 네트워크 사용이 필요한 React Native 애플리케이션에서 선호되는 API 레이어로 자리 잡았습니다. 2025년 후반에 출시된 Apollo Client 4.0은 모바일 환경을 위해 특별히 설계된 20-30% 작은 번들과 개선된 TypeScript 지원을 제공하는 경량 아키텍처를 도입했습니다. > **Apollo Client 4.0 주요 변경 사항** > > Apollo Client 4.0은 React 전용 export를 `@apollo/client/react`로 분리했습니다. React 19 Suspense와 React Compiler를 지원하며, 모놀리식 `ApolloError`를 디버깅 개선을 위한 특정 에러 클래스로 대체했습니다. ## React Native에서 Apollo Client 4 설정하기 설치 과정은 간단합니다. Apollo Client 4.0은 Expo와 베어 React Native 프로젝트 모두에서 작동합니다. ```bash # Installation npm install @apollo/client graphql ``` 클라이언트 초기화에는 네트워크 요청을 위한 `HttpLink`와 로컬 상태 관리를 위한 `InMemoryCache`가 필요합니다. ```typescript // src/apollo/client.ts import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client'; const httpLink = new HttpLink({ uri: 'https://api.example.com/graphql', // Enable text streaming for @defer and subscriptions fetchOptions: { reactNative: { textStreaming: true }, }, }); export const apolloClient = new ApolloClient({ link: httpLink, cache: new InMemoryCache({ typePolicies: { Query: { fields: { // Merge paginated results products: { keyArgs: ['category'], merge(existing = [], incoming) { return [...existing, ...incoming]; }, }, }, }, }, }), }); ``` `typePolicies` 설정은 무한 스크롤이 있는 모바일 앱에서 일반적인 요구 사항인 페이지네이션 데이터의 캐시 정규화를 처리합니다. ## ApolloProvider로 앱 래핑하기 프로바이더 패턴은 Apollo Client를 React 컴포넌트 트리에 연결합니다. 일반적으로 `App.tsx` 또는 Expo Router 레이아웃의 루트 레벨에 배치합니다. ```tsx // App.tsx import { ApolloProvider } from '@apollo/client/react'; import { apolloClient } from './src/apollo/client'; import { RootNavigator } from './src/navigation'; export default function App() { return ( ); } ``` Apollo Client 4.0은 메인 진입점이 아닌 `@apollo/client/react`에서 React 훅을 import합니다. 이 변경으로 코어 클라이언트가 React가 아닌 컨텍스트에서 실행될 때 번들 크기가 줄어듭니다. ## 타입 안전한 GraphQL 쿼리 작성하기 GraphQL Code Generator는 스키마에서 TypeScript 타입을 생성하여 런타임 타입 불일치를 제거합니다. 클라이언트 플러그인과 함께 설치합니다. ```bash # Install codegen tools npm install -D @graphql-codegen/cli @graphql-codegen/client-preset ``` codegen 설정은 스키마를 지정하고 출력 위치를 지정합니다. ```typescript // codegen.ts import type { CodegenConfig } from '@graphql-codegen/cli'; const config: CodegenConfig = { schema: 'https://api.example.com/graphql', documents: ['src/**/*.tsx', 'src/**/*.ts'], generates: { './src/gql/': { preset: 'client', config: { documentMode: 'string', }, }, }, }; export default config; ``` `npx graphql-codegen`을 실행하면 `useQuery` 훅이 사용하는 타입이 지정된 document 노드가 생성됩니다. ## useQuery로 데이터 페칭하기 `useQuery` 훅은 로딩 상태, 에러, 캐시 업데이트를 관리합니다. Apollo Client 4.0은 더 예측 가능한 상태 전환을 위한 `dataState` API를 도입했습니다. ```tsx // src/screens/ProductListScreen.tsx import { useQuery } from '@apollo/client/react'; import { graphql } from '../gql'; import { ActivityIndicator, FlatList, Text, View } from 'react-native'; const GET_PRODUCTS = graphql(` query GetProducts($category: String!, $limit: Int, $offset: Int) { products(category: $category, limit: $limit, offset: $offset) { id name price imageUrl } } `); export function ProductListScreen({ category }: { category: string }) { const { data, loading, error, fetchMore } = useQuery(GET_PRODUCTS, { variables: { category, limit: 20, offset: 0 }, // Fetch from cache first, then network fetchPolicy: 'cache-and-network', // Keep previous data while fetching new notifyOnNetworkStatusChange: true, }); if (error) { return Error: {error.message}; } const loadMore = () => { fetchMore({ variables: { offset: data?.products.length ?? 0 }, }); }; return ( item.id} renderItem={({ item }) => } onEndReached={loadMore} onEndReachedThreshold={0.5} ListFooterComponent={loading ? : null} /> ); } ``` `cache-and-network` 페치 정책은 서버에서 새로고침하는 동안 캐시된 데이터를 즉시 표시합니다. 이 패턴은 모바일 네트워크에서 체감 지연 시간을 줄입니다. ## 뮤테이션과 낙관적 업데이트 뮤테이션은 서버 데이터를 수정하고 로컬 캐시를 업데이트합니다. 낙관적 응답은 서버가 변경을 확인하기 전에 즉각적인 피드백을 제공합니다. ```tsx // src/hooks/useAddToCart.ts import { useMutation } from '@apollo/client/react'; import { graphql } from '../gql'; const ADD_TO_CART = graphql(` mutation AddToCart($productId: ID!, $quantity: Int!) { addToCart(productId: $productId, quantity: $quantity) { id items { id product { id name } quantity } totalPrice } } `); export function useAddToCart() { const [addToCart, { loading }] = useMutation(ADD_TO_CART, { // Optimistic response for instant UI feedback optimisticResponse: ({ productId, quantity }) => ({ addToCart: { __typename: 'Cart', id: 'current-cart', items: [], totalPrice: 0, }, }), // Update cache after mutation update(cache, { data }) { if (!data?.addToCart) return; cache.modify({ id: cache.identify({ __typename: 'Cart', id: 'current-cart' }), fields: { items: () => data.addToCart.items, totalPrice: () => data.addToCart.totalPrice, }, }); }, }); return { addToCart, loading }; } ``` `cache.modify` 메서드는 전체 쿼리를 다시 가져오지 않고 캐시된 필드를 직접 업데이트합니다. 이 접근 방식은 셀룰러 연결에서 네트워크 요청을 최소화합니다. ## 모바일 앱에서 네트워크 에러 처리하기 Apollo Client 4.0은 일반적인 `ApolloError`를 특정 에러 클래스로 대체했습니다. 정적 `.is()` 메서드를 통해 타입 안전한 에러 처리가 가능합니다. ```tsx // src/components/ErrorBoundary.tsx import { NetworkError, GraphQLErrors } from '@apollo/client/errors'; import { Text, Button, View } from 'react-native'; interface Props { error: Error; onRetry: () => void; } export function QueryErrorHandler({ error, onRetry }: Props) { // Network failure (offline, timeout, DNS) if (NetworkError.is(error)) { return ( Connection failed. Check your internet.