2 min read

React Query Offline-First 전략

네트워크 불안정 환경에서 캐시 우선 UX를 구현하기 위한 staleTime, persistence, sync 패턴

React Query Offline-First 전략 thumbnail

도입

모바일 네트워크가 불안정한 환경에서는 데이터 조회 실패가 곧바로 이탈로 이어진다. React Query를 기본 설정으로만 쓰면 로딩 스피너를 반복 노출하게 되고, 사용자는 동일 화면에서 상태가 튀는 경험을 하게 된다. 이 글은 캐시 우선 렌더링, 오프라인 큐, 온라인 복구 시점 동기화를 결합해 서비스 체감 품질을 높이는 실전 패턴을 정리한다.

React Query Offline-First 전략 커버
Wikimedia Commons 기반 무료 이미지

문제 정의

오프라인 우선 전략이 실패하는 이유는 대부분 라이브러리 설정값이 아니라 제품 정책이 빠져 있기 때문이다. 다음 세 가지가 흔한 실패 조건이다.

  • 동일 Query Key에 사용자 컨텍스트를 포함하지 않아 계정 전환 시 캐시가 섞인다.
  • mutation 재시도 정책이 화면 흐름과 분리되어, 사용자는 성공처럼 보이지만 서버 반영은 실패한다.
  • staleTime과 gcTime을 일괄 적용해 트래픽 패턴별 최적화가 불가능하다.

핵심은 네트워크 상태를 UX 상태와 동일하게 취급하지 않는 것이다. 오프라인이어도 읽기는 허용하고, 쓰기만 큐에 넣는 식으로 기능별 정책을 분리해야 한다.

핵심 개념

관점설계 기준검증 포인트
조회 정책캐시 우선 + 백그라운드 재검증첫 화면 렌더 시 API 호출 차단 여부
쓰기 정책오프라인 큐 + 서버 idempotency재전송 중복 반영 여부
복구 정책online 이벤트 시 순차 flush복구 직후 데이터 충돌률
관측 지표cache hit rate + retry success세션당 실패 체감 횟수

오프라인 전략은 프론트엔드만의 문제가 아니다. 백엔드가 idempotency-key를 지원하지 않으면 큐 전략은 장기적으로 데이터 오염을 만든다. 따라서 API 계약과 함께 설계해야 한다.

코드 예시 1: QueryClient 기본 정책 분리

import { QueryClient } from "@tanstack/react-query";

export const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 30_000,
      gcTime: 10 * 60_000,
      retry: 1,
      refetchOnWindowFocus: false,
      networkMode: "offlineFirst",
    },
    mutations: {
      retry: 3,
      networkMode: "offlineFirst",
    },
  },
});

export const key = {
  feed: (userId: string) => ["feed", userId],
};

코드 예시 2: 오프라인 큐 flush

type PendingWrite = { id: string; endpoint: string; body: unknown; key: string };

const queue: PendingWrite[] = [];

export async function flushPendingWrites() {
  for (const item of queue) {
    const response = await fetch(item.endpoint, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Idempotency-Key": item.key,
      },
      body: JSON.stringify(item.body),
    });

    if (!response.ok) break;
  }
}

window.addEventListener("online", () => {
  void flushPendingWrites();
});

아키텍처 흐름

Mermaid diagram rendering...

트레이드오프

  • staleTime을 길게 잡으면 API 호출은 줄지만 데이터 신선도 관리 책임이 UI로 이동한다.
  • offline queue를 넣으면 UX는 좋아지지만 서버 idempotency를 반드시 맞춰야 한다.
  • 재시도 횟수를 높이면 성공률은 오르지만, 실패 원인 진단 로그가 없으면 장애 대응이 느려진다.

정리

React Query Offline-First의 핵심은 옵션 최적화가 아니라 운영 계약이다. 조회/쓰기/복구를 분리하고, API와 함께 재시도 규칙을 명시하면 네트워크 품질이 낮은 환경에서도 안정적인 사용자 경험을 유지할 수 있다.

이미지 출처

  • Cover: source link
  • License: CC BY-SA 3.0 / Author: Dave Gandy
  • Note: Wikimedia Commons 무료 라이선스 이미지를 다운로드 후 1600px 기준 JPG로 최적화했습니다.

댓글