モバイルAPI向けのJSONとProtobuf:サイズ・互換性・デバッグ
モバイルAPIでのJSONとProtobufを比較。ペイロードサイズ、互換性、デバッグのトレードオフと、テキストかバイナリかを選ぶ実践的なルールを解説します。
ライブダッシュボードや進捗更新で gRPC ストリーミングと REST ポーリングのどちらが有利かを事例と注意点(モバイル・ファイアウォール)とともに解説します。

TicketCreated、TicketStatusChanged、JobProgressUpdated のようなイベントを定義し、UIが反応するために必要な最小フィールドだけを含めます。\n\n実践的な設計フローの例:\n\n- 各UI要素に最大許容遅延をマークする(100 ms、1 s、10 s)。\n- イベントタイプと各イベントの最小ペイロードを定義する。\n- 切断後にクライアントがどう回復するかを決める(フルスナップショット、またはカーソルから再開)。\n- 遅いクライアントに対するルールを決める(バッチ、折りたたみ、古い更新の破棄、または送信頻度の削減)。\n- ストリーミング不可時のフォールバックを選ぶ。\n\n再接続の扱いで多くのチームが詰まります。基本戦略としては:接続時にスナップショット(現在の状態)を送り、その後増分イベントを送る。サポートするなら「last event id」のようなカーソルを含め、クライアントが「18452以降を送って」と要求できるようにします。これで再接続時の挙動が予測可能になります。\n\nバックプレッシャーは「クライアントが処理できない場合は?」という問題です。ライブダッシュボードでは更新を折りたたむのが多くの場合許容されます。進捗が41%、42%、43%と進んでいる間に端末が忙しければ、最後の43%だけ送れば良いことが多いです。\n\nまたストリーミングが使えないときでも製品が使えるようにフォールバックを計画します。一般的には一時的に5〜15秒ごとのポーリングに切り替えるか、重要度の低い画面には手動更新ボタンを置きます。\n\nAppMasterで構築する場合、多くは「ホット」更新のイベント駆動フローとフォールバック用の標準API読み取りという二つの経路にきれいにマップします。\n\n## 実例:ライブダッシュボードとジョブ進捗更新\n\n在庫200SKUを表示する倉庫ダッシュボードを想像してください。RESTポーリングではブラウザが /inventory を5秒ごとに呼び出し、フルJSONリストを受け取りテーブルを再描画します。大半の時間で何も変わらないのに、繰り返しリクエスト、繰り返しフルレスポンス、繰り返しパースのコストを払い続けます。\n\nストリーミングではフローが逆転します。クライアントは長期間生きるストリームを開き、まず初期スナップショットを受け取ってUIをすぐに描画し、その後何かが変わった行だけ小さな更新を受け取ります。\n\n典型的なダッシュボードの流れ:\n\n- 初期状態:SKUのフルリスト、数量、行ごとの「最終更新」タイムスタンプ。\n- 増分更新:変化した行だけ(例:SKU-184 が 12 から 11 に変わった)。\n- 新鮮さの信号:全体の「データが〜時点の現在」表示でユーザーの信頼を得る。\n\n次に別画面として長時間走るジョブ(CSVインポートや月次請求生成)を考えます。ポーリングは不自然なジャンプ(0%、0%、0%、80%、完了)を生みますが、ストリーミングは落ち着いて正直に見せます。\n\n進捗ストリームは通常、小さく頻繁なスナップショットを送ります:\n\n- 完了率(0〜100)\n- 現在のステップ("Validating"、"Matching"、"Writing")\n- ETA(ベストエフォートで変化する)\n- 最終結果(成功、警告、エラーメッセージ)\n\nデルタとスナップショットの選択は重要です。在庫のような用途ではデルタが小さくて効率的です。ジョブ進捗は各メッセージが小さいためスナップショットを使う方が安全で、クライアントが再接続してメッセージを一つ逃しても混乱が少ないことがあります。\n\nAppMasterのようなプラットフォームで作ると、初期状態の読み取りモデルとイベント風の増分更新がマップしやすく、UIはAPIを叩き続けずに応答性を保てます。\n\n## モバイルクライアントでは何が変わるか\n\nスマホでは「継続接続」はデスクトップとは違った挙動をします。ネットワークはWi-Fiとセルラーを行き来し、トンネルがリセットされ、ユーザーがエレベーターに入るなどで接続が途切れます。大きな変化は「単一のリクエスト」から「いつでも消えるセッション」を想定する設計に切り替わることです。\n\n切断を期待し、安全に再生できる設計をしましょう。良いストリームには "last event id" のようなカーソルを含め、アプリが再接続して「ここから再開して」と言えるようにします。これがないと重複更新(同じ進捗が二回出る)や欠落(40%からいきなり90%に飛ぶ)が起きます。\n\nバッテリーはストリーミングで改善することが多いですが、メッセージが小さく意味あるものである場合に限ります。毎秒フルオブジェクトを送るのはデータとバッテリーを急速に消費します。"order 183 status changed to Shipped" のようなコンパクトなイベントを好みましょう。\n\nアプリがバックグラウンドに入るとOSがストリーミングを停止または終了してしまうことが多いです。フォールバックを計画しましょう:最後に知っている状態を表示し、フォアグラウンドに戻ったときに再同期する。重要な通知はプラットフォームのプッシュ通知を使い、ユーザーがタップしたときにアプリを開いて再同期させます。\n\nモバイル向けの実践例:\n\n- 再接続はバックオフを入れる(カバレッジが悪いときにバッテリーを消費しないため)。\n- イベントIDかタイムスタンプを含め、更新を冪等にして重複がUIを壊さないようにする。\n- 意味のあるデルタを送り、低優先度の更新はバッチする。\n- 接続時にスナップショットを送り、続けてライブイベントを適用する。\n- メッセージに簡単なバージョニング(メッセージタイプ+オプションフィールド)を付けて古いアプリでも動くようにする。\n\nAppMasterでモバイルアプリを作る場合、ストリームは「あると良いもの」であって「唯一の真実」ではないと扱うのが実用的です。短時間の切断時でもUIが使えるようにしましょう。\n\n## ファイアウォール、プロキシ、HTTP/2の落とし穴\n\nストリーミングは紙の上では明白な利点に見えますが、実ネットワークが介入すると事情が変わることがあります。大きな違いは接続です:ストリーミングは多くの場合長時間維持されるHTTP/2接続を使い、企業プロキシやミドルボックス、厳格なセキュリティ設定と相性が悪いことがあります。\n\n企業ネットワークはTLSインスペクション(トラフィックの復号・再暗号化)を行うことがあり、それがHTTP/2ネゴシエーションを壊したり、長時間のストリームをブロックしたり、動作を静かに変更したりします。症状としてはランダムな切断、ストリームが始まらない、更新が滑らかではなくバーストで届く、などが出ます。\n\n従来のgRPCはHTTP/2が必須です。プロキシがHTTP/1.1しか話さない場合、通常のRESTは通ってもgRPC呼び出しは失敗することがあります。ブラウザ環境ではgRPC-Webがより一般的なHTTPインフラを通すために使われます。\n\n### ロードバランサ、アイドルタイムアウト、キープアライブ\n\nネットワークがHTTP/2を許可していても、インフラはアイドルタイムアウトを持つことが多いです。長時間静かなストリームはロードバランサやプロキシにより切断されます。\n\n一般的な対策:\n\n- サーバーとクライアントで適切なキープアライブピングを設定する(頻度は高すぎないように)。\n- ロードバランサやリバースプロキシのアイドルタイムアウトを延ばす。\n- 長い静寂期間がある場合は小さなハートビートを送る。\n- 再接続をきれいに扱う(状態を再開できるようにし、重複イベントを避ける)。\n- クライアントとサーバー双方で切断理由をログに残す。\n\n### gRPC-Webやフォールバックを選ぶべきとき\n\nユーザーが厳格な企業ネットワークの背後にいる場合、ストリーミングはベストエフォートとして扱いフォールバックチャネルを用意してください。典型的にはネイティブアプリではgRPCストリーミングを使い、ブラウザ経由ではgRPC-Web(または短いRESTポーリング)を許す分岐を設けます。\n\nユーザーが実際に使う環境からテストしましょう:\n\n- 企業オフィスネットワーク(プロキシ方針あり)\n- 公共Wi‑Fi\n- VPN接続\n- モバイルキャリアネットワーク\n\nAppMasterでAppMaster Cloudや主要クラウドプロバイダにデプロイする場合、ローカル開発だけでなく実環境でエンドツーエンドに挙動を検証してください。\n\n## よくある間違いと罠\n\n最大の罠はストリーミングをデフォルト扱いにすることです。リアルタイムは気持ちが良いですが、サーバー負荷、モバイルのバッテリー消費、サポート問い合わせを静かに増やすことがあります。どの画面が本当に数秒以内の更新を必要とするかを厳密に判断して、30〜60秒ごとに更新して良い画面と区別しましょう。\n\nもう一つのよくある間違いは毎回フルオブジェクトを送ることです。200 KBのJSON塊を毎秒プッシュするライブダッシュボードは、最初の忙しい時間までは良く見えますが、その瞬間に破綻します。小さなデルタを優先してください:"order 4832 status changed to shipped" のように、全注文を再送しない。\n\nセキュリティは多くのチームが軽視します。長時間のストリームでも強い認証と認可チェックが必要で、トークン切れがストリーム中に起きることを想定する必要があります。ユーザーがプロジェクトへのアクセスを失ったら、サーバーは直ちに更新を送るのをやめるべきです。\n\n再接続の挙動は実運用で多くのアプリが壊れるポイントです。特にモバイルでは、Wi‑FiとLTEの切り替え、スリープ、バックグラウンド化が頻繁に起こります。いくつかの習慣が深刻な失敗を防ぎます:切断を前提とする;last-seenイベントID(またはタイムスタンプ)から再開できるようにする;更新を冪等にしてリトライで重複が起きないようにする;遅いネットワーク向けにタイムアウトとキープアライブを設定する;ストリーミング失敗時の劣化モード(更新頻度を下げる)を提供する。\n\n最後に、多くのチームはストリーミングを可視化せずに出荷します。切断率、再接続ループ、メッセージ遅延、ドロップした更新を追跡してください。ジョブ進捗ストリームでサーバー側が100%なのにクライアントが20秒間70%で止まっているなら、遅延がどこにあるのか(サーバー、ネットワーク、クライアント)を示すメトリクスが必要です。\n\n## ストリーミングを選ぶ前の簡単チェックリスト\n\nユーザーにとって「リアルタイム」が何を意味するかを決めましょう。\n\nまずレイテンシを決めます。ダッシュボードがライブに感じる必要があるなら1秒未満の更新がストリームを正当化します。ユーザーが10秒〜60秒の範囲で良ければ、単純なポーリングがコストと単純さで勝ることが多いです。\n\n次にファンアウトを見ます。同じデータを多くの人が同時に監視する(壁掛けの運用画面+50個のブラウザ)なら、ポーリングは継続的なバックグラウンド負荷に変わります。ストリーミングは繰り返しリクエストを削減できますが、多数のオープン接続を扱う必要がある点に注意してください。\n\n簡易チェックリスト:\n\n- 変更はどれくらい速く表示される必要があるか:1秒未満、約10秒、または約1分か?\n- 同じデータを同時に監視するクライアントは何人で、どれくらいの時間見るか?\n- クライアントが30秒オフラインになったらどうすべきか:古いデータを表示、更新をバッファ、または状態を再読み込みするか?\n- ネットワーク経路はHTTP/2をエンドツーエンドでサポートするか(プロキシやロードバランサ含む)?\n- 本番でストリーミングが壊れた場合の安全なフォールバック(短いポーリング等)があるか?\n\n失敗と回復についても考えてください。ストリーミングは動作すると素晴らしいですが、難しいのは再接続、見逃したイベント、UIの一貫性維持です。実用的な設計は高速パスにストリーミングを使い、再接続後に現在状態を再構築するための再同期アクション(1回のRESTコール)を定義しておくことです。\n\nプロトタイプでダッシュボードを素早く作る場合(例えばAppMasterのノーコードUIで)、このチェックリストを早期に適用して、更新要件を理解する前にバックエンドを過剰設計しないようにしましょう。\n\n## 次のステップ:小さなストリームをパイロットして安全に拡張する\n\nストリーミングはスイッチを入れるものではなく「得るもの」と考えてください。新鮮さに価値が明確にある箇所を一つ選び、他はそのままにしてデータを取るべきです。\n\n単一の高価値ストリームから始めましょう。長時間ジョブの進捗(ファイルインポート、レポート生成)やライブダッシュボード上の1つのカード(本日の注文、アクティブチケット、キュー長)などが良い候補です。スコープを小さく保つことで、ポーリングと実データで比較しやすくなります。\n\n簡単なパイロット計画:\n\n- 成功を定義する:目標更新遅延、許容切断率、モバイルでの「十分に良い」基準。\n- 最小のストリームを出荷する:1種類のメッセージ、1画面、1つのバックエンドエンドポイント。\n- 基本を計測する:サーバーCPU/メモリ、オープン接続数、メッセージ遅延、再接続頻度、クライアントのバッテリー影響。\n- フォールバックを追加する:ストリームが失敗またはネットワークがブロックしたら自動で遅いポーリングに落とす。\n- 慎重に拡張する:メトリクスを説明できるようになってからフィールドや画面を追加する。\n\nフォールバックを意図的に残しておいてください。企業ネットワークや古いプロキシ、厳しいファイアウォールはHTTP/2を邪魔することがあり、モバイルネットワークはアプリのバックグラウンド化で不安定になります。優雅にダウングレードできれば空白画面やサポートが減ります。\n\n重いカスタムコードを書かずにこれを出荷したいなら、AppMaster(appmaster.io)はバックエンドロジック、API、UIを素早く作って要件に合わせて反復する手助けになります。小さく始めて価値を証明し、ストリームはポーリングより明確に優れている箇所だけに追加してください。