本文へスキップ
Starone

ケイパビリティ

実際の端末、ネットワーク、リリース上の制約を前提に設計するモバイルアプリケーション

モバイルアプリケーションは、チームが任意のタイミングで再デプロイできない、長寿命のクライアントです。断続的なネットワーク上で動作し、OSによって予告なく終了させられ、古いバージョンのまま何か月もインストールされ続けます。私たちはこうした事実を前提に、アプリケーション、API、リリースパイプラインを設計します。

概要

モバイルエンジニアリングは、構造的に3つの点でWebエンジニアリングと異なります。ネットワークは断続的であるため、アプリケーションは通信がなくても役に立ち、回復したときに整合を取らなければなりません。プロセスのライフサイクルはOSが制御し、メモリとバッテリーを守るためにアプリケーションをサスペンドまたは終了させます。リリースはストア審査を経たうえでユーザーによるアップデートに依存するため、常に複数のバージョンが使われており、不具合を再デプロイで取り下げることはできません。

こうした制約は、クライアントだけでなくシステム全体の形を決めます。APIは何か月も前に出荷されたバージョンとの互換性を保ち、ペイロードは従量制の回線に適したものでなければならず、認証はアプリケーションがバックグラウンドにある間にトークンが失効しても破綻しないようにする必要があります。端末上では、認証情報はハードウェアに裏付けられたストレージに保管し、ローカルデータにはあらゆるデータベースと同様にスキーマとマイグレーションが必要で、起動時間、フレームレート、メモリ、消費電力は計測すべき特性です。

私たちは、iOSではSwiftとSwiftUI、AndroidではKotlinとJetpack Composeで開発し、コードベースの共有が有利なトレードオフとなる場合はFlutterまたはReact Nativeを用います。どれを選ぶかはプロダクトの要件とチーム構成に基づいて判断し、バックエンドとのコントラクト、オフラインモデル、リリースプロセスは最初の画面と並行して設計します。

エンジニアリング領域

技術領域

01

ネイティブ開発とクロスプラットフォーム開発

ネイティブ開発では、すべてのプラットフォームAPIをすぐに利用でき、起動とレンダリングの特性が最も優れ、プラットフォーム標準の挙動が得られますが、コードベースが2つになります。Flutterは独自のエンジンで独自のウィジェットを描画し、プラットフォーム間で高い視覚的一貫性を実現します。React NativeはJavaScriptまたはTypeScriptからネイティブビューを駆動し、Webチームとスキルを共有できます。いずれも、一部の連携にはネイティブコードが必要です。

  • Swift、SwiftUI、UIKit
  • Kotlin、Jetpack Compose、コルーチン
  • FlutterとDart
  • New ArchitectureとHermesを用いたReact Native
  • ビジネスロジック共有のためのKotlin Multiplatform
  • ネイティブモジュールとプラットフォームチャネル
02

オフラインファーストのデータと同期

オフラインファーストの設計では、UIはローカルデータベースに対して読み書きを行い、同期エンジンがバックグラウンドでサーバーとの整合を取ります。ローカルでの書き込みは冪等性キー付きのミューテーションとしてキューに積み、接続が回復したときに順番にリプレイします。コンフリクトの扱いはエンティティごとに定義します。メモに適したルールが、決済に適したルールであるとは限らないためです。

  • Room、GRDB、Drift、WatermelonDBを用いたSQLite
  • 冪等性キー付きのミューテーションアウトボックス
  • カーソルまたは変更トークンによる差分同期
  • Last-Write-Wins、フィールド単位のマージ、CRDT
  • 金融に関わる状態はサーバーを正とするルール
  • WorkManagerとBGTaskSchedulerによるバックグラウンド同期
03

セキュリティ、ストレージ、認証

シークレットはiOSのKeychainとAndroidのKeystoreに保管し、端末が対応している場合は、鍵をSecure EnclaveまたはStrongBoxに裏付けられたセキュアエレメント内で生成します。生体認証は、ハードウェアが保持する鍵の使用を制御します。つまり、照合の成功は、改ざんされたアプリケーションが回避できてしまう真偽値を返すのではなく、暗号処理の実行を許可します。サインインには、システムブラウザを介したPKCE付きのOAuth 2.0認可コードフローを用います。

  • KeychainとAndroid Keystore
  • Face ID、Touch ID、CryptoObjectを用いたBiometricPrompt
  • PKCE付きのOAuth 2.0とリフレッシュトークンのローテーション
  • ローテーション計画を伴う証明書ピンニング
  • App AttestとPlay Integrity
  • ジェイルブレイク、root化、改ざんのシグナル
  • 機密データの画面キャプチャとバックアップからの除外
04

モバイルAPIアーキテクチャ、プッシュ通知、ディープリンク

BFF(Backend for Frontend)はレスポンスを画面に合わせて整形し、高レイテンシなネットワークでの往復回数を減らします。APNsとFCMによるプッシュ通知はベストエフォートであるため、状態を取得するきっかけとして扱い、状態そのものを運ぶ手段としては決して扱いません。Universal LinksとAndroid App Linksは、検証済みドメインでホストするファイルを通じてURLをアプリケーションに紐づけるため、別のアプリケーションがそのURLを横取りすることを防げます。

  • クライアント種別ごとのBFF
  • カーソルページネーションとフィールドの選択的取得
  • 圧縮、ETag、条件付きリクエスト
  • APNsとFirebase Cloud Messaging
  • Universal LinksとAndroid App Links
  • 最低サポートバージョンと強制アップデート
  • リモートコンフィグとフィーチャーフラグ
05

パフォーマンス、アナリティクス、クラッシュレポート

パフォーマンス改善の対象は、コールドスタート、フレームペーシング、メモリ、消費電力です。1フレームは60 Hzで約16.7ミリ秒、120 Hzで約8.3ミリ秒以内に生成する必要があるため、処理はメインスレッドの外で行い、リストは仮想化します。クラッシュとハングのレポートは、アップロードしたdSYMとR8のマッピングファイルでシンボリケートし、リリースごとのクラッシュフリーセッション率として追跡します。

  • コールドスタートと最初のフレームまでの時間のプロファイリング
  • Xcode InstrumentsとAndroid Studio Profiler
  • Baseline ProfilesとR8による最適化
  • 画像のキャッシュとダウンサンプリング
  • 無線の起動回数を抑えるリクエストのバッチ化
  • Firebase CrashlyticsとSentry
  • プライバシーに配慮したプロダクトアナリティクス
06

CI/CDとストア配信

モバイルのパイプラインは、クリーンなマシンから再現可能な形でビルド、署名、テスト、配布を行い、署名用のIDはシークレットストアで保持し、個人のノートPCには決して置きません。ビルドは、内部テスト、TestFlight、Playのテストトラックを経て、App Storeの段階的リリースまたはGoogle Playの段階的公開へ進みます。クラッシュ率やANR率が悪化した場合は、自動または手動でロールアウトを停止します。

  • Fastlane、Xcode Cloud、GitHub Actions、Bitrise
  • コード署名、プロビジョニングプロファイル、Play App Signing
  • ユニットテスト、スナップショットテスト、デバイスファームでのUIテスト
  • TestFlightと、Playの内部・クローズド・オープンの各トラック
  • App Storeの段階的リリースとGoogle Playの段階的公開
  • ストアのメタデータ、プライバシー申告、審査用メモ

モバイルアプリケーションとクラウドネイティブなバックエンドの接続

モバイルクライアントは、エッジ層を通じてバックエンドに到達します。まずCDNとWebアプリケーションファイアウォール、次にAPIゲートウェイがあり、ゲートウェイはTLSを終端し、トークンを検証し、端末単位・ユーザー単位のレート制限を適用し、リクエストをルーティングします。ゲートウェイの背後では、BFFがKubernetesまたはサーバーレス基盤上で動くドメインサービスへの呼び出しを集約し、画面に合わせて整形した1つのレスポンスを返します。これにより、呼び出し回数の多いオーケストレーションは、1回の呼び出しが1ミリ秒で済むデータセンター内にとどまり、数百ミリ秒かかるモバイルネットワーク上には出てきません。

アイデンティティはOpenID Connectを通じて流れます。アプリケーションはシステムブラウザを開き、PKCE付きの認可コードフローを完了して、有効期間の短いアクセストークンとローテーションされるリフレッシュトークンを受け取り、KeychainまたはKeystoreに保管します。ゲートウェイはトークンの署名を検証し、検証済みのクレームを下流に渡します。各サービスは、そのクレームに照らしてリクエストごとに認可を行います。App AttestやPlay Integrityによるアテステーションは、呼び出し元が改変されていない正規のビルドであることを示すシグナルとして追加できます。高リスクの操作には有用ですが、サーバー側の認可の代わりには決してなりません。

サーバー側で発生した状態変化は、3つの経路で端末に届きます。APNsとFCMによるプッシュ通知は、アプリケーションを起こすかユーザーに知らせ、データの取得を促します。WebSocketまたはServer-Sent Eventsの接続は、アプリケーションがフォアグラウンドにある間にライブ更新を運び、OSの制限に従ってバックグラウンドでは切断します。起動時と復帰時の差分同期がすべての欠落を埋めるため、プッシュ通知が届くかどうかに正しさが依存することはありません。サーバー側では、これらは他のコンシューマーを駆動するのと同じイベントストリームから供給され、通知サービスがイベントをデバイストークンへファンアウトします。

  • バージョン互換性:アプリケーションはすべてのリクエストでバージョンとプラットフォームを送信する。APIは追加のみで進化させ、バックエンドは最低サポートバージョン未満に対してアップデートを要求できる
  • レジリエンス:クライアント側のタイムアウト、バックオフを伴うリトライ、冪等性キーにより、接続断の後でもミューテーションを安全にリプレイできる
  • 効率:圧縮とページネーションを施したレスポンス、条件付きリクエスト、端末に合わせたサイズの画像バリアントにより、通信量とバッテリー消費を抑える
  • メディア:アップロードはアプリケーションサーバーを経由せず、署名付きで再開可能なURLを通じてオブジェクトストレージへ直接行う
  • オブザーバビリティ:端末で生成したトレースIDをゲートウェイと各サービスへ伝播させ、遅い画面をエンドツーエンドで追跡できるようにする

アーキテクチャ

モバイルアプリケーションのバックエンド
  1. モバイルアプリ

    • iOS (Swift)
    • Android (Kotlin)
    • Flutter
    • オフラインデータストア
  2. エッジ

    • CDN
    • APIゲートウェイ
    • 認証
    • レート制限
  3. BFF / モバイルAPI

    可能な限り1画面を1往復で取得

    • 画面単位のレスポンス
    • APIバージョニング
    • 同期エンドポイント
    • フィーチャーフラグ
  4. サービス

    • アカウント
    • コンテンツ
    • 決済
    • メディア処理
  5. データ・通知

    • PostgreSQL
    • Redis
    • オブジェクトストレージ
    • APNs・FCMプッシュ
  6. オブザーバビリティ

    • クラッシュレポート
    • APIトレーシング
    • リリースヘルス
    • クライアント分析
モバイルクライアントはBFF(Backend for Frontend)と通信します。BFFは画面ごとにレスポンスを整形し、サービス側の変更からアプリを保護します。古いバージョンのアプリは市場で使われ続けるため、APIのバージョニングとリリースヘルスもアーキテクチャの一部です。

オフラインファーストのアーキテクチャと同期のコンフリクト

オフライン対応には段階があります。読み取りキャッシュは、接続がなくても最後に取得したデータを表示するもので、低コストです。書き込みのキューイングは、ユーザーがオフラインでも操作できるようにするもので、順序付きのアウトボックス、冪等なサーバーエンドポイント、目に見える保留状態が必要です。ローカルデータベースをUIにとっての信頼できる情報源とし、双方向に同期する完全なオフラインファーストは、最も高機能であると同時に最も複雑です。フィールドサービス、物流、点検のように、ユーザーが長時間にわたり圏外で作業する場合に選ぶべきものです。

コンフリクトは、同期と同期の間に、同じレコードが2台の端末で、あるいは端末とサーバーの双方で変更されたときに発生します。サーバーのタイムスタンプによるLast-Write-Winsはシンプルですが、一方の編集を黙って破棄します。これは設定値には許容できますが、共有ドキュメントには許容できません。フィールド単位のマージは、重ならない編集を保持します。CRDTは、共同編集のテキストやリストを自動的に収束させますが、メタデータの増加とデータモデルの難しさという代償を伴います。残高、在庫、予約については、キューに積まれた各操作をサーバーが現在の状態に照らして検証し、拒否することがあるため、アプリケーションはその拒否を分かりやすく提示しなければなりません。

同期ではさらに、トゥームストーンによる削除の扱い、まだアップロードされていないデータに対するスキーママイグレーション、バッチの途中で起きる部分的な失敗にも対処する必要があります。端末の時計は信頼できないため、順序付けにはサーバーが割り当てるバージョンまたは論理クロックを用い、端末のローカル時刻は決して使いません。

ネイティブかクロスプラットフォームか:選び方

判断の決め手は、プロダクトのうちどれだけがプラットフォーム固有であるかです。フォーム、リスト、API駆動のコンテンツが中心のアプリケーションは共有に向いており、FlutterまたはReact Nativeの単一コードベースにより、機能開発の重複の大半がなくなり、2つのプラットフォームの足並みも揃います。一方、カメラのパイプライン、Bluetooth周辺機器、バックグラウンドでの位置情報、オンデバイス機械学習、ウィジェット、ウォッチ向けコンパニオン、最新のOS機能を中心に構築するアプリケーションは、労力の多くをネイティブとの境界に費やすことになり、クロスプラットフォームの層は作業を減らさないまま間接層を増やすだけになります。

チーム構成は技術と同じくらい重要です。TypeScriptとReactに習熟したWebチームはReact Nativeですぐに生産性を発揮できます。FlutterはDartの習得が必要になる代わりに、レンダリングをより厳密に制御できます。ネイティブチームはツールチェーン全体を自ら掌握しており、新しいOSバージョンが出荷されたときにフレームワークのリリーススケジュールに左右されません。Kotlin Multiplatformはその中間の道で、ネットワーク、永続化、ドメインロジックを共有しつつ、UIは完全にネイティブで構築します。

どれを選ぶにせよ、ある程度のネイティブの専門知識は必要です。署名、プッシュ通知の設定、ストアへの申請、ディープリンクの関連付け、パフォーマンスプロファイリング、そして多くのサードパーティSDKはプラットフォーム固有であり、その知識を持たないクロスプラットフォームのチームは、まさにそうした箇所で行き詰まります。

エンジニアリングの進め方

私たちのアプローチ

私たちは、クライアント、API、リリースプロセスを一体として設計します。古いバージョンがインストールされているかぎり、1つの判断が他の2つを制約し続けるためです。

  1. 01

    プラットフォームの範囲と制約の定義

    対象とするOSバージョン、端末クラス、オフライン要件、規制およびストアポリシー上の制約、そしてプロダクトが依存する端末機能を確定します。これらが、ネイティブかクロスプラットフォームかの判断を決めます。

  2. 02

    APIコントラクトと同期モデルの設計

    エンドポイント、ページネーション、エラーのセマンティクス、冪等性、旧バージョンに対する互換性ポリシーを、バックエンドチームとともに仕様化します。オフラインでの書き込みが必要な場合は、ストレージのコードを書く前に、エンティティごとのコンフリクトルールを決定します。

  3. 03

    アーキテクチャとパイプラインの早期確立

    MVVMやMVIといった単方向データフロー、依存性注入、モジュール化したプロジェクト構成、ローカルの永続化層を整えると同時に、開発の最初の週からテスターに届く署名済みのCIビルドを用意します。

  4. 04

    基盤へのセキュリティの組み込み

    認証フロー、セキュアストレージ、生体認証による保護、通信路のセキュリティ、アテステーションを共通基盤として実装し、機能開発がそれらに依存する前にOWASP MASVSに照らしてレビューします。

  5. 05

    実機と実際のネットワークでのテスト

    ユニットテストとスナップショットテストはコミットごとに実行し、UIテストは古いハードウェアやOSバージョンを含むデバイスマトリクス上で実行します。ネットワークコンディショニングでパケットロス、遅延、リクエスト途中の切断を再現し、プロセス終了のテストで状態の復元を検証します。

  6. 06

    段階的なリリースとデータの監視

    ビルドは内部トラックとベータトラックを経て、本番環境への段階的なロールアウトへ進みます。公開範囲を広げる前に、クラッシュフリー率、ANR率、起動時間、主要なファネルイベントを前バージョンと比較します。

トレードオフ

設計を左右する判断

アーキテクチャを確定する前に、お客様のチームとともに検討する問いです。

ネイティブ、Flutter、React Nativeのどれを選ぶか
プロダクトがプラットフォームとの深い統合、要求の厳しいグラフィックス、新しいOS機能の即時採用に依存しており、両プラットフォームに人員を配置できる場合は、ネイティブを選びます。1つのチームでプラットフォーム間に一貫した独自のUIを提供したい場合はFlutterを、TypeScriptとReactの専門性があり、コードと人員をWebと共有したい場合はReact Nativeを選びます。コストを半減させることだけを理由にクロスプラットフォームを選ぶことは避けるべきです。プラットフォーム固有の作業がなくなるわけではないためです。
プロダクトにはどの程度のオフライン機能が必要か
読み取りキャッシュは既定で採用します。低コストで、空白の画面の大半をなくせます。電波状況の悪い場所でもユーザーが操作を完了しなければならず、かつ操作が本質的に冪等である場合は、書き込みのキューイングを追加します。双方向同期を伴う完全なオフラインファーストに踏み切るのは、長時間のオフライン作業が中核のユースケースである場合に限ります。コンフリクトの解決、未同期データのマイグレーション、サポートの複雑さが継続的なコストになるためです。
モバイルアプリケーション専用のBFFを持つべきか
画面が複数のサービスのデータを必要とする場合、モバイルとWebで表示内容が異なる場合、汎用APIが端末に必要な量をはるかに超えるデータを返す場合は、持つべきです。BFFは、古いアプリケーションバージョンへの対応を1か所にまとめる場所にもなります。APIもクライアントも1つしかない小規模なプロダクトでは不要です。集約するものがないまま、デプロイ対象が1つ増えるだけになります。
証明書ピンニングを使うべきか
決済、健康データ、認証情報を扱い、侵害されたネットワークや端末上での傍受が脅威モデルに含まれるアプリケーションでは、ピンニングを行います。中間証明書の公開鍵、またはバックアップ鍵を含む鍵のセットに対してピンニングし、検証済みのローテーション手順を用意します。フォールバックのないままピンが失効すると、インストール済みのすべてのアプリがバックエンドから締め出されるためです。リスクの低いアプリケーションでは、プラットフォームのトラストストアとCertificate Transparencyの組み合わせが妥当なベースラインです。
まだ使われている古いアプリケーションバージョンをどうサポートするか
APIは追加のみで進化させ、クライアントには未知のフィールドやenum値を無視させ、新しい挙動はサーバー主導のフラグで制御します。バックエンドから最低サポートバージョンを公開し、アプリケーションがアップデートを促す、または必須にできるようにします。古いAPIの挙動を廃止するのは、アナリティクスで利用が合意済みのしきい値を下回ったことを確認してからです。これは最初のリリースから計画しておく必要があります。すでに出荷したバージョンに後から組み込むことはできません。
ストア審査を待たずに修正を配信できるか
サーバー主導の設定とフィーチャーフラグを使えば、両プラットフォームで挙動を即座に無効化または変更できます。React Nativeアプリケーションでは、ストアのポリシーの範囲内でJavaScriptバンドルのOTA(Over-the-Air)アップデートも配信できます。対象となるのは修正や軽微な変更であり、アプリケーションの主目的を変えるような変更は含まれません。ネイティブコードの変更には必ず新しいバイナリと審査が必要になるため、リスクのある機能はリモートのキルスイッチを備えた状態で出荷すべきです。

本番対応

本番運用に耐える条件

セキュリティの確保

トークンと鍵は、ハードウェアによる保護と、生体認証または端末の認証情報によるアクセス制御のもとでKeychainとKeystoreに保持し、機密情報はログ、平文の設定ストア、バックアップ、タスクスイッチャーのスクリーンショットのいずれにも書き込みません。通信にはTLSを用い、脅威モデルが求める場合はピンニングを加えます。リリースビルドは難読化し、デバッグフラグが残っていないことを確認します。クライアントは信頼できないものとして扱い、重要なルールはすべてサーバー側で改めて強制します。

スケーリング

モバイルにおけるスケールとは、多数のバージョンにまたがって増え続ける端末群を意味します。そのため、CDN、ゲートウェイでの端末単位のレート制限、ページネーションされキャッシュ可能なレスポンスによって、バックエンド側で負荷を受け止めます。プッシュ通知のファンアウトは、送信をバッチ化し無効なトークンを除去する、キューを背後に持つ通知サービスが担います。コードベースは、明示的なインターフェースを持つ機能モジュールによってスケールさせ、チームが拡大してもビルド時間とマージコンフリクトを抑えます。

監視

クラッシュ、ハング、ANRのレポートはシンボリケートしてリリースごとにグループ化し、ブレッドクラム(直前の操作履歴)と端末のコンテキストを付与します。パフォーマンスモニタリングでは、コールドスタート、遅延フレームとフリーズフレーム、ネットワークリクエストのレイテンシを実機から記録し、トレースIDによってクライアントのリクエストをバックエンドのスパンに関連付けます。アナリティクスイベントはバージョン管理されたスキーマに従い、同意とプラットフォームのトラッキング規則を尊重します。

デプロイ

パイプラインは、タグ付けされたコミットから署名済みでバージョン管理されたビルドを生成し、シンボルをアップロードし、TestFlightとPlayのテストトラックへ自動で提出します。本番環境では、App Storeの段階的リリースとGoogle Playの段階的公開を利用し、どちらも一時停止が可能です。審査にかかる時間は保証されないため、リリース計画にはその余裕を織り込み、緊急時の緩和策はリモートフラグに頼ります。

システム連携

アプリケーションはOpenID Connectを通じてIDプロバイダーと連携し、決済、地図、メッセージング、アナリティクスのSDKは内部インターフェースの背後に置いて、それぞれを置き換えたりテストでスタブ化したりできるようにします。サードパーティSDKは1つずつ、サイズ、起動コスト、権限、データ収集の観点で評価します。その挙動を、App Storeのプライバシーラベルと、Playのデータセーフティフォームで申告しなければならないためです。

使用技術

ワークロードとお客様の既存環境に合わせて選定します。

  • Swift and SwiftUI
  • Kotlin and Jetpack Compose
  • Flutter
  • React Native
  • Kotlin Multiplatform
  • SQLite
  • Firebase Cloud Messaging
  • Apple Push Notification service
  • Firebase Crashlytics
  • Sentry
  • Fastlane
  • GitHub Actions
  • TestFlight
  • Google Play Console

ゼロから本番へ

エンジニアリングライフサイクル

  1. 01

    アイデア

  2. 02

    ディスカバリー

  3. 03

    システムアーキテクチャ

  4. 04

    UX・プロダクトデザイン

  5. 05

    アプリケーション開発

  6. 06

    AI・データレイヤー

  7. 07

    クラウドインフラ

  8. 08

    セキュリティ

  9. 09

    QA・パフォーマンス

  10. 10

    デプロイ

  11. 11

    オブザーバビリティ

  12. 12

    継続的な進化

FAQ

よくあるご質問

ネイティブとクロスプラットフォームのどちらで開発すべきですか

プロダクトのうちどれだけがプラットフォーム固有であるか、そしてどのようなチームがあるかによって決まります。コンテンツやワークフローが中心のアプリケーションはFlutterやReact Nativeで共有しやすく、カメラ、Bluetooth、バックグラウンド処理、新しいOS機能を土台とするプロダクトは、通常SwiftとKotlinのほうが適しています。最もリスクの高い端末連携について短期間の技術検証(スパイク)を行うほうが、比較表よりも確実に答えが出ます。

プッシュ通知は実際にはどのような仕組みで動いていますか

アプリケーションはiOSではAPNs、AndroidではFCMに登録してデバイストークンを受け取り、それをバックエンドに送信します。バックエンドはプラットフォームのサービスに対し、そのトークン宛てのメッセージ配信を依頼し、プラットフォームは端末に到達可能になった時点で配信します。配信はベストエフォートで、遅延したり、まとめられたり、破棄されたりすることがあり、トークンも変わります。そのため、バックエンドは無効なトークンに対処し、アプリケーションは正となる状態をAPIから取得する必要があります。

ストア審査にはどのくらい時間がかかりますか。リジェクトの原因は何ですか

審査時間は一定ではなく、どちらのストアも保証していないため、所要時間が固定であるという前提でリリースを計画すべきではありません。リジェクトのよくある原因には、プライバシー申告の不備、アカウント削除機能の欠如、目的が明確でない権限リクエスト、審査担当者がサインインできないこと、アプリ内課金のルールに抵触する決済フローなどがあります。申請のたびにテスト用の認証情報と審査用メモを添えることで、その多くを回避できます。

端末上の機密データはどのように保護しますか

認証情報と鍵は、ハードウェアに裏付けられた保護のもとでKeychainまたはKeystoreに保管し、より大きな機密データセットはそこに保持した鍵で暗号化します。生体認証のチェックは暗号鍵に紐づけるため、条件分岐にパッチを当てて回避することはできません。機密性の高い画面はスクリーンショットとバックアップの対象から除外し、サーバーは、クライアントがルールを強制済みであることを決して前提にしません。

1つのバックエンドでWebとモバイルの両方のクライアントに対応できますか

はい、可能です。ドメインサービスとデータは共有し、クライアント種別ごとの薄いBFFがそれらを適合させます。モバイル向けのBFFは、回数が少なく、小さく、バージョン差に寛容なレスポンスを重視し、Web向けのBFFはWebのデプロイに合わせて変更できます。これにより、ビジネスルールを1か所に保ちつつ、各クライアントがそれぞれのリリースサイクルで進化できます。

本番環境で動くシステムが必要な方へ

構築しようとしているものをお聞かせください。エンジニアが内容を拝見し、2営業日以内にご返信します。