1. HOME
  2. ブログ
  3. 開発ノート
  4. Rustで構築するオフライン同期対応Flutterタスク管理アプリ開発ノート
BLOG

ブログ

開発ノート

Rustで構築するオフライン同期対応Flutterタスク管理アプリ開発ノート

プロジェクト背景と目的

グローバル化が進む今日、分散チームでのタスク管理はリアルタイムな情報共有とオフライン環境への対応が求められます。特に現場作業者や外出先での利用を想定すると、ネットワーク断や低帯域環境でも操作ができ、切断復帰後に自動同期される仕組みが不可欠です。本開発ノートでは、Flutter をフロントエンドに、Rust 製 CRDT ライブラリと SQLite/Hive などのローカル DB を組み合わせたオフライン同期対応タスク管理アプリを構築した経験をもとに、要件定義から技術選定、アーキテクチャ設計、オフライン同期実装、CI/CD、テスト戦略まで詳細に解説します。開発受託を依頼する際に必須となる見積もり項目や開発会社選定のポイントも整理しています。

要件定義とユースケース整理

要件定義フェーズでは、以下の主要ユースケースを挙げ、Given/When/Then 形式で定義しました。

  • 分散チームのメンバーがネットワーク接続がない環境でもタスクの作成・編集・完了操作を行える

  • オンライン復帰時に、他メンバーの変更と自動でマージし、最新状態を取得できる

  • 削除や移動などの競合が発生してもデータ不整合を起こさない

  • プッシュ通知でタスクの割り当てや期限切れをリアルタイムに受け取る

  • Web(管理画面)とモバイルアプリで同一データをシームレスに共有できる

非機能要件では、最大同時オフライン操作数 100 件、同時同期操作数 50 件、同期遅延 5 秒以内、データ損失率 0 件を目指すことを定義。さらに、アプリ起動初期化は 3 秒以内、1 日あたりのバッテリー消費追加 5% 以下を目標としました。これらを WBS にタスク・工数と紐付けて、見積もり依頼の精度を高めています。

システムアーキテクチャ設計

本アプリのアーキテクチャは大きく「モバイルクライアント層」「同期エンジン層」「バックエンド同期 API 層」「管理 Web 層」の四層構成です。

  • モバイルクライアント層:Flutter(Dart)で開発し、ローカルデータには Hive、SQLite を組み合わせて使用。UI レイヤーは Provider + Riverpod で状態管理。

  • 同期エンジン層:Rust 製の CRDT(Conflict-free Replicated Data Type)ライブラリを Wasm 経由で Dart FFI から呼び出し、操作ログを操作 ID 単位でバッファリング。

  • バックエンド同期 API 層:gRPC または REST で同期リクエストを受け、Redis Streams や Kafka で変更イベントを処理。Delta Sync パターンを採用し、差分のみを交換。

  • 管理 Web 層:Next.js + TypeScript で開発した管理画面から、ユーザー・チーム・権限設定やタスク統計を操作可能。GraphQL API でデータ提供。

モバイルクライアントはオフライン時に操作ログをローカルに永続化し、オンライン復帰時に同期エンジンが自動でバックエンドとすり合わせを行います。同期状態は StatusNotifier で UI に反映し、同期中・完了・競合発生を表示します。

オフライン同期実装と CRDT 導入

オフライン同期部分の要となるのが CRDT です。従来の Operational Transformation 方式と比べ、CRDT は状態ベースと操作ベースの両アプローチをサポートし、不正な順序や再送にも強い特性を持ちます。本プロジェクトでは、Rust 製の Automerge ライブラリを選定し、次のように利用しています。

  1. タスク操作(作成・更新・完了・削除)を Rust 側のオペレーションとして登録

  2. Dart FFI で Wasm モジュールを呼び出し、内部状態を更新

  3. オペレーションログを Vec<Op> として Dart 側に返却し、Hive/SQLite に保存

  4. 同期 API 呼び出し時にはログバッファをバックエンドへ送信し、成功時に削除

競合解消は自動マージを基本とし、同一フィールドの同時更新時のみ最新タイムスタンプ優先で解決。より複雑な競合は管理画面の「競合解決ビュー」から手動で調整可能とし、柔軟性を担保しました。

Flutter アプリケーション構成とプラグイン活用

Flutter 側では、以下のプラグインとパッケージを組み合わせて開発効率を向上させています。

  • flutter_riverpod:状態管理の一貫性を維持

  • drift(旧 moor):型安全な SQLite 操作

  • hive_flutter:キー・バリュー型キャッシュに利用

  • flutter_local_notifications:ローカル通知とプッシュ通知トリガー

  • grpc:同期用 gRPC クライアント実装

  • flutter_secure_storage:エンドツーエンド暗号化トークン管理

各プラグインは抽象レイヤーでラッピングし、テスト時にはモック実装に差し替え可能。これによりユニットテストの網羅性を高め、依存関係のバージョンアップ時も影響範囲を最小化できます。

UI/UX設計と画面遷移フロー

UI/UX では、分散チームのコミュニケーションを重視し、次の設計を行いました。

  • メインタスクリスト画面:ユーザーごとのタブ表示、検索/フィルタ/ソート機能を上部に配置

  • タスク詳細画面:コメント機能、ファイル添付、サブタスク表示をタブ切り替えで実装

  • チームビュー:カンバン方式でのドラッグ&ドロップ操作をサポート

  • 同期ステータスバー:画面下部に常時表示し、オフライン中は黄色、同期中は青、完了は緑で色分け

  • 競合解決ビュー:CRDT 競合発生時のみモーダル表示し、変更履歴と差分プレビューから最終状態を選択

Figma を使ったプロトタイピングを経て、ユーザーテストを 15 名規模で実施。平均タスク完了操作時間を従来比 40% 短縮する結果を得ました。

テスト戦略と自動化

モバイルクライアントと同期エンジン、バックエンド API は多層構造のため、各層ごとに最適化されたテストを構築します。まずユニットテストでは、Flutter 側の Riverpod プロバイダ、Drift/Hive 操作、Dart FFI 呼び出しのモックを組み合わせ、ローカル DB への書き込み・読み込み、状態遷移のバリデーションを網羅します。Rust 製 CRDT ライブラリは cargo test でオペレーションベースと状態ベース双方の整合性を検証し、不整合ケースやパフォーマンス低下を未然に検出します。

統合テストフェーズでは、GitHub Actions 上に Android/iOS エミュレータ、Rust CLI、バックエンド同期サーバを Docker Compose で同時起動し、Flutter Driver や integration_test パッケージを用いて「オフラインでタスク作成→再起動→オンライン復帰→自動マージ」の E2E シナリオを自動化。同期ログの矛盾チェックや Taclog(同期履歴)を検証し、同期遅延と競合解決の再現性を確認します。

パフォーマンステストとしては、1000 件単位のタスク同期ストレステストを k6 や Locust で実施し、同期エンジンのバッチサイズ調整とバックプレッシャー制御が適切に動作するかを検証。Flutter の UI スループットは flutter_driver の Timeline 解析で 60fps を維持できるか、SQLite/Hive のスループットは 200ms 以内で完了するかを定量評価し、CI ジョブで SLA 達成を自動判定します。

モニタリングとログ集約

開発ノートの要件として、運用開始後の状態可視化が欠かせません。バックエンド同期 API は OpenTelemetry Rust SDK を組み込み、gRPC リクエストから同期結果返却までのトレースを Jaeger に送信。各マイクロサービスのレイテンシ分布、エラー箇所が可視化され、問題箇所の特定が迅速化されます。

デバイス側では、Flutter 側に logger パッケージを導入し、アプリ内の同期ステータス、CRDT 競合発生時のログを構造化 JSON でファイル出力。Vector/Fluent Bit を使ってこれらを集約し、Elasticsearch に転送。Kibana 上で「同期失敗」「オフライン期間」「競合解決回数」といったカスタムダッシュボードを作成し、運用チームがビジネス指標と紐付けて分析可能としました。

Prometheus/Grafana の統合では、バックエンドの同期レート、バッチサイズ、Rust エンジンのメモリ使用率、Flutter アプリのメトリクスを収集。アプリ破棄数や再起動率、同期遅延分布をグラフ化し、Alertmanager で「同期レート低下」「メモリ爆発」のアラートを Slack と PagerDuty へ通知。これにより、SRE チームが 15 分以内に対応に入れる体制を整備しました。

セキュリティとデータ保護

分散チームのタスク情報には機密性があるため、クライアント側でもデータ保護を徹底します。Flutter 側のローカル DB は SQLCipher(SQLite の暗号化版)を導入し、Hive も HiveAesCipher で暗号化。鍵は flutter_secure_storage を通じて OS の Keystore/Keychain に安全に格納します。

同期 API 通信は gRPC over TLS1.3 を採用し、クライアント証明書を mTLS で相互認証。バックエンドでは Vault で管理する JWT シークレットを使用し、トークンは短命化。Dart の grpc パッケージで認証ハンドラを実装し、不正アクセスやトークン偽造を防止します。

CRDT 操作ログの改ざん防止には、操作ごとに SHA-256 ハッシュを付与し、連鎖ハッシュ(チェーン構造)で整合性検証を行います。バックエンド同期時には hash-chain の正当性チェックを挟み、改ざん履歴が検出された場合は同期を中断しアラートを出す仕組みを追加。さらに、管理 Web 層の GraphQL API には RBAC を適用し、権限ないユーザーからの履歴参照や手動競合解決を制限しています。

CI/CD パイプラインとリリース

継続的インテグレーションには GitHub Actions を利用し、プルリクエストごとに以下を実行します。

  • flutter analyzedart format でコード品質チェック

  • flutter testcargo test でユニットテスト

  • drift_dev で DB スキーマ生成検証

  • Rust → Wasm コンパイルと Wasmtime テスト

  • flutter driver による簡易 UI テスト

マージ後はステージング環境へ自動デプロイし、Firebase Test Lab を使った実機テスト、Rust CI Runner 上でのエッジエミュレータテストをパスすると本番リリースへプロモーション。Flutter は fastlane で Android/iOS 向けバージョン管理とリリースノート自動生成を行い、Changelog は Conventional Commits 形式で一貫性を保ちます。

デプロイメントは Canary ロールアウトをサポートし、10%→30%→100% の順で新バージョンを展開。問題発生時は自動で前バージョンへロールバックする機能を実装し、ダウンタイムゼロリリースを実現しています。

運用保守体制と Runbook

運用フェーズでは、DevOps と SRE チームが連携し、24×7 オンコール体制を整備。Runbook は Confluence 上で管理し、主な障害対応手順を網羅します。

  • オフライン同期失敗:flutter logs で最後のエラーを取得し、同期バッファを手動クリア

  • DB マイグレーション異常:flutter pub run drift:generate 再実行+アプリ再起動

  • mTLS 認証エラー:新規証明書の発行と edge-sync cert rotate コマンドによる更新

  • Canary 失敗:GitHub Release の自動ロールバックラベルをクリックし、前バージョン復元

四半期ごとに障害シミュレーション演習を行い、平均 MTTR(平均復旧時間)を 90 分から 45 分に短縮。運用指標は Grafana ダッシュボードで可視化し、KPI として「同期成功率 99.9%」「障害対応 SLA 達成率 95%」を設定しています。

コストシミュレーションと予算管理

本アプリの初期開発費用は以下の通り見積もりました。

  • 要件定義・設計:400万円

  • Flutter 開発:600万円

  • Rust CRDT ライブラリ連携:300万円

  • 同期 API/バックエンド:500万円

  • CI/CD/IaC 整備:200万円

  • テスト&品質保証:300万円

  • 運用支援・ガイド作成:200万円
    合計:約2,500万円

ランニングコストとしては、Firebase Authentication/Firestore(月額10万〜20万円)、REST/gRPC ホスティング(GKE/EKS 月額15万〜30万円)、Prometheus/Grafana Cloud(月額5万〜10万円)、Flutter の Crashlytics & Performance(月額5万〜8万円)を含め年間約360万〜680万円と試算。AWS Budgets や GCP Billing でタグ別可視化し、月次レポートと Slack 通知で予算超過を即時検知します。

システム開発会社選びのポイント

オフライン同期対応アプリの受託先を選定する際は、以下の観点で複数社に同一フォーマットの要件定義書・WBSを提示し、見積もり比較を行いましょう。

  1. Flutter/Dart 実装実績:Riverpod+Drift でのオフライン対応事例

  2. Rust FFI 連携力:Wasm 経由 CRDT ライブラリ組み込み経験

  3. 同期 API 構築:gRPC または REST+Redis Streams/Kafka 実績

  4. CI/CD+IaC:GitHub Actions+Terraform+fastlane 自動化ノウハウ

  5. SRE/運用体制:オンコール/Runbook 整備実績

  6. UI/UX テスト:Flutter Driver/Firebase Test Lab 実機テスト経験
    費用相場は、小規模(1,500万〜2,500万円)、中規模(3,000万〜4,500万円)、大規模(5,000万〜7,000万円)をベンチマークし、固定価格型・時間単価型いずれの条件も照らし合わせ、コスト削減と費用対効果の最適化を図りましょう。

まとめ

本開発ノートでは、Flutter+Rust CRDT を活用したオフライン同期対応タスク管理アプリの要件定義から CI/CD、テスト戦略、可観測性、セキュリティ、運用保守、コストシミュレーション、開発会社選びのポイントまで網羅的に解説しました。分散チームでの業務効率化を実現するため、まずは PoC を通じて同期品質と UX を検証し、複数社の見積もり比較を経て最適なパートナーとともに本格導入を進めてください。見積もり依頼はこちらからどうぞ。

お問合せ

不明点やお見積りの依頼などお気軽にください。




問い合わせを行う

関連記事