RORK LABEN
RORK MAX — Rork MaxがiPhone・iPad・Apple Watch・Apple TV・Vision Pro向けのネイティブSwiftアプリを生成できるようになりましたPUBLISH — Rork Maxは Xcode不要の「2クリックApp Store公開」に対応。申請・公開までの摩擦を大きく減らしますEXPO — 標準のRorkはReact Native(Expo)ベースで、プレーンな英語の説明からiOS/Androidネイティブアプリを生成しますPRICING — Rorkは無料で始められ、有料プランは月額$25から。個人開発で試しやすい価格帯ですFUNDING — Rorkがa16z(Andreessen Horowitz)から$2.8Mを調達。AIアプリビルダー領域への資金流入が続いていますREVIEW — 実運用では生成コードの可読性・保守性、Expo由来の制約、課金・プッシュ・広告SDKの組み込みやすさが評価の鍵になりますRORK MAX — Rork MaxがiPhone・iPad・Apple Watch・Apple TV・Vision Pro向けのネイティブSwiftアプリを生成できるようになりましたPUBLISH — Rork Maxは Xcode不要の「2クリックApp Store公開」に対応。申請・公開までの摩擦を大きく減らしますEXPO — 標準のRorkはReact Native(Expo)ベースで、プレーンな英語の説明からiOS/Androidネイティブアプリを生成しますPRICING — Rorkは無料で始められ、有料プランは月額$25から。個人開発で試しやすい価格帯ですFUNDING — Rorkがa16z(Andreessen Horowitz)から$2.8Mを調達。AIアプリビルダー領域への資金流入が続いていますREVIEW — 実運用では生成コードの可読性・保守性、Expo由来の制約、課金・プッシュ・広告SDKの組み込みやすさが評価の鍵になります
記事一覧/開発ツール
開発ツール/2026-06-14上級

Rork アプリの API 通信を障害に強くする — Circuit Breaker・指数バックオフ・タイムアウトを実装で固める

Rork で生成したアプリの API 通信を本番品質に引き上げる実装メモ。タイムアウト・指数バックオフ・Circuit Breaker を段階的に組み込み、依存 API が不安定でも自動回復する通信層を設計します。

Rork401API通信Circuit Breaker指数バックオフタイムアウト2React Native158本番運用10

プレミアム記事

リリース直後のアプリで、API のエラー率が一晩で 5% を超えたことがあります。

依存していた外部 API が応答を遅延させ始め、タイムアウトを持たない fetch がそのまま詰まっていく。画面にはスピナーが回り続け、ユーザーには何が起きているのか伝わらない。ログを追って原因にたどり着いた頃には、すでに数百件のエラーレポートが積み上がっていました。あのとき通信層に最低限の防御があれば、被害は十分の一で済んだはずです。

個人開発でアプリを回していると、こうした通信の防御は後回しになりがちです。Rork でアプリを組むと、生成される API 呼び出しは素直な fetch です。開発中はそれで困りません。問題は、本番のネットワークが開発環境とはまるで別物だという点にあります。地下鉄で電波が切れ、Wi-Fi と 5G を行き来し、依存サービスが数分だけ不調になる——こうした揺らぎを前提にした通信層を、後付けではなく設計として持っておきたいところです。

ここでは Rork アプリの通信を本番品質へ引き上げる過程を、実際に動くコードとともに実装メモとして残します。派手な仕組みではありません。タイムアウト、指数バックオフ付きのリトライ、Circuit Breaker。この三つを正しい順序で重ねるだけで、依存 API が傾いてもアプリが巻き添えにならない通信層になります。

素の fetch が本番で崩れる三つの瞬間

最初に、何から守るのかをはっきりさせておきます。Rork が吐く典型的な呼び出しはこの形です。

const fetchUser = async (userId: string) => {
  const res = await fetch(`https://api.example.com/users/${userId}`);
  if (!res.ok) throw new Error("Failed to fetch user");
  return res.json();
};

このコードが本番で崩れる瞬間は、経験上ほぼ三つに集約されます。

一つ目は一時的な切断です。モバイル回線は一瞬で復活することが多く、本来なら一度リトライすれば通る通信を、そのままエラーとしてユーザーに見せてしまいます。二つ目は無限待機です。fetch にはタイムアウトがないため、応答しないサーバーを待ち続け、スピナーが何十秒も回ります。三つ目が連鎖障害です。遅い API を待つリクエストが積み上がり、すでに壊れている相手へ送り続けることで、自分側の状態まで悪化させます。

この三つに、それぞれタイムアウト・リトライ・Circuit Breaker が対応します。導入する順序もこの通りが現実的です。効果が出るのが早く、実装コストが低いものから入れていきます。

まずタイムアウト — 今日入れて一番効く一手

無限待機を断つだけで、ユーザー体感のエラーの大半は消えます。2026 年時点では AbortSignal.timeout() が React Native でも使えるようになり、AbortController を手で組む必要が薄れました。ただし「どのエラーがタイムアウト由来か」を呼び出し側で判別できるよう、独自のエラー型に正規化しておきます。

export class ApiError extends Error {
  constructor(
    message: string,
    public readonly statusCode: number,
    public readonly body?: unknown,
  ) {
    super(message);
    this.name = "ApiError";
  }
}
 
interface TimedFetchOptions extends RequestInit {
  timeoutMs: number;
}
 
export async function fetchWithTimeout(
  url: string,
  { timeoutMs, signal, ...init }: TimedFetchOptions,
): Promise<Response> {
  // 呼び出し側の signal(アンマウント等)と timeout を合成する
  const timeoutSignal = AbortSignal.timeout(timeoutMs);
  const merged = signal
    ? AbortSignal.any([signal, timeoutSignal])
    : timeoutSignal;
 
  try {
    const res = await fetch(url, { ...init, signal: merged });
    if (!res.ok) {
      const body = await res.json().catch(() => null);
      throw new ApiError(`HTTP ${res.status} ${res.statusText}`, res.status, body);
    }
    return res;
  } catch (err) {
    // timeout 由来の中断を 408 に正規化し、呼び出し側で扱いやすくする
    if (err instanceof DOMException && err.name === "TimeoutError") {
      throw new ApiError(`Request timed out after ${timeoutMs}ms`, 408);
    }
    throw err;
  }
}

タイムアウト値は一律にしないほうが扱いやすいです。私は用途で三段階に分けています。一覧取得のような軽い GET は 5〜8 秒、ユーザー操作に紐づく詳細取得は 8〜12 秒、アップロードや重い処理は 30〜60 秒。短すぎると低速回線のユーザーに不要なエラーを見せ、長すぎると無限待機の問題が戻ってきます。AbortSignal.any() で画面側の中断シグナルと合成しておくと、コンポーネントがアンマウントされた瞬間に通信も確実に止まります。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
タイムアウト→リトライ→Circuit Breaker を段階導入する実装順序と、それぞれの具体的なしきい値の決め方
AbortSignal.timeout() と指数バックオフ+ジッターを組み合わせた、コピーして動く通信クライアントの全コード
Circuit Breaker の状態をスナップショットで観測し、TanStack Query と二重リトライさせない統合パターン
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

開発ツール2026-06-13
Rork 製 Expo アプリを Kotlin ネイティブへ移せる構造にしておく — Android Studio 移行エージェント発表を受けた設計の見直し
Android Studio の React Native→Kotlin 自動移行エージェント発表を受け、Rork 製 Expo アプリを「移せる構造」に保つ設計を整理。ネイティブ依存の棚卸しスクリプト、コア層の分離パターン、移行準備度チェックリストを実例つきで紹介します。
開発ツール2026-06-13
「さくら」で検索すると「サクラ」が出てこない — Rork 製アプリのアプリ内検索と日本語の正規化
ひらがなで検索するとカタカナのタイトルが出てこない——個人開発の壁紙アプリで踏んだ日本語検索の取りこぼしを、NFKC 正規化・かな変換・事前インデックス化の3手順で解消した実装メモです。Rork への指示文例も載せています。
開発ツール2026-06-12
Android 17 で「ポートレート固定」が通用しなくなる — Rork 製 Expo アプリの大画面対応を前倒しで済ませる手順
Android 17 では大画面デバイスでの画面固定・リサイズ制限が無視されるようになります。Rork で生成した Expo アプリの影響判定からレイアウト改修、エミュレータだけで済ませる検証手順までを実例ベースでまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →