データストレージはモバイルアプリケーションの主要なタスクの一つであり、パフォーマンス、セキュリティ、ユーザーエクスペリエンスに影響を与えます。この記事では、SQLite、Room、Core Data、Realm、Firebase Firestore、SharedPreferences、DataStore、Keystore、Keychain、そしてシリアライゼーションフォーマット(JSON、Protobuf)とライブラリ(Gson、Moshi、kotlinx.serialization)について解説します。このガイドは初心者開発者が適切なデータストレージソリューションを選択するのに役立ちます。詳細はAndroidデータストレージの公式ガイドをご覧ください。
主なポイント
エンティティ間に関係を持つ構造化データを保存するには、リレーショナルデータベースが使用されます。
SQLiteは、あらゆるモバイルプラットフォームで動作する組み込み型リレーショナルデータベースです。個別のサーバーを必要とせず、データは単一のファイルに保存されます。SQLiteはRoom(Android)の基盤であり、オプションでCore Data(iOS)の基盤でもあります。ライブラリ:android.database.sqlite(Android)、FMDB/Core Data(iOS)、sqflite(Flutter)。
Roomは、SQLiteを扱うための公式Android Architecture Componentsライブラリです。Entity(テーブル)、DAO(クエリ)、Database(エントリポイント)というORMレイヤーを提供します。Roomはコンパイル時にSQLクエリをチェックし、コルーチンとFlowをサポートし、スキーマを自動的にマイグレーションします。
@Entity data class User( @PrimaryKey val id: Int, val name: String, val email: String ) @Dao interface UserDao { @Query("SELECT * FROM user WHERE id = :id") suspend fun getUser(id: Int): User? }
Core Dataは、オブジェクトグラフを管理するAppleのフレームワークです。純粋なデータベースではなく、SQLite、XML、バイナリストレージ上の永続化レイヤーです。Core Dataはオブジェクト(NSManagedObject)、リレーションシップ、スキーマバージョニング、アンドゥ/リドゥ、NSManagedObjectContextによるマルチスレッドを管理します。
RealmはSQLiteの代替として設計された高性能モバイルデータベースです。Realmは読み取りと書き込みでSQLiteよりも高速で、リアクティブ通知(Live Objects)、オンザフライ暗号化、クロスプラットフォーム(Android、iOS、Flutter、React Native)をサポートします。欠点:APK/IPAサイズの増加とメモリ使用量の増加。
少量のデータ(設定、トークン、キャッシュ)を保存するには、単純なキー値ストアが使用されます。
SharedPreferencesはAndroidのレガシーキー値ストアです。欠点:同期アクセス(読み取り時にUIをブロック)、型付けの欠如、大きなファイル読み込み時のANRリスク。新しいプロジェクトには推奨されません。
DataStoreはGoogleによるSharedPreferencesの現代的な代替品です。Kotlin CoroutinesとFlowを介して非同期に動作し、Preferences DataStore(キー値)とProto DataStore(Protobufによる型付きデータ)をサポートします。DataStoreはUIスレッドに対して安全で、トランザクションをサポートします。
UserDefaultsはiOSの小さな設定用標準ストレージです。プリミティブ型、文字列、日付、Dataをサポートします。UserDefaultsは同期型であるため、大量のデータには適していません。register(defaults:)による値の登録でデフォルト値を設定します。
デバイス間の同期が必要なアプリケーションでのデータ保存には、Firebaseクラウドデータベースが使用されます。
Firebase Firestoreは、リアルタイムサブスクリプション、自動スケーリング、強力なクエリ、組み込みのオフラインモードを備えたNoSQLドキュメントデータベースです。データはコレクションとドキュメント(JSONのような構造)に編成されます。Firestoreはトランザクションとバッチ操作をサポートします。チャット、フィード、ソーシャルアプリに最適です。
Firebase Realtime Databaseは、データを単一のJSONツリーとして保存する古いFirebase NoSQLデータベースです。Firestoreよりシンプルですが、クエリとスケーリングの柔軟性に劣ります。シンプルなリアルタイムアプリケーション(オンラインステータス、シンプルなチャット)に推奨されます。
| 特徴 | Cloud Firestore | Firebase Realtime DB |
|---|---|---|
| データモデル | コレクション → ドキュメント | JSONツリー |
| クエリ | 複雑(フィルタリング、並べ替え、制限) | 単純(キーによる) |
| スケーリング | 自動 | 手動シャーディング |
| オフラインモード | あり(永続キャッシュ) | あり |
| 料金 | 読み取り/書き込み操作ごと | トラフィック + ストレージごと |
トークン、パスワード、暗号化キーの保存には、特別な保護されたストレージが必要です。
Android Keystoreは、暗号化キーのためのシステムストレージです。キーはハードウェア環境(TEE — Trusted Execution Environment)に保存され、アプリやOSからアクセスできません。キー生成、暗号化、署名をサポートします。Android 9+にはStrongBox Keymaster(専用チップ)が含まれています。
Keychain Servicesは、パスワード、キー、証明書のための安全なiOSストレージです。データはハードウェアSecure Enclaveを使用して暗号化されます。Keychainはアクセシビリティレベルをサポートします:Always、WhenUnlocked、WhenUnlockedThisDeviceOnly、AfterFirstUnlock。
EncryptedSharedPreferencesは、AES256-GCMとHKDFによるキーと値の暗号化を備えたSharedPreferencesのラッパーです。AndroidX Securityライブラリに実装されています。トークンや機密設定の保存に推奨されます。
IT Sectrでは、リフレッシュトークンと生体認証ベースのキーの保存にAndroid Keystore + EncryptedSharedPreferencesを使用しています。iOSでは、最大限のセキュリティのためにkSecAttrAccessibleWhenUnlockedThisDeviceOnlyレベルのKeychainを使用しています。
ファイルストレージ(画像、動画、ドキュメント)には、モバイルプラットフォームがいくつかの種類のストレージを提供しています。
AndroidはInternal Storage(/data/data/パッケージ/ — プライベートストレージ)とExternal Storage(SDカードまたはエミュレートされたパーティション)を区別します。Cache Directoryはシステムがクリアできる一時ストレージです。Scoped Storage(Android 10+)はExternal Storageへのアクセスを制限します — アプリは自分のファイルまたはMediaStore/SAF経由のファイルのみを表示します。
iOSはDocuments Directory(iCloudバックアップ、永続データ)、Library/Caches(一時ファイル、バックアップなし)、Tmp Directory(一時的、クリア可能)を提供します。ファイルシステムを操作するにはNSFileManagerを使用します。iOS 11+はクラウドファイル用のFile Providerをサポートします。
シリアライゼーションは、オブジェクトを送信または保存用の形式に変換します。デシリアライゼーションはその逆のプロセスです。
JSON(JavaScript Object Notation)は最も一般的なフォーマットです:読みやすく、柔軟で、すべてのプラットフォームでサポートされています。XMLはより厳格で、レガシーシステムで使用されています。Protobuf(Protocol Buffers)はGoogleのバイナリフォーマットです:JSONより3〜10倍コンパクトで、解析が高速で、厳格なスキーマを持ちます。高負荷システムやマイクロサービスで使用されます。
JSONSerializationはJSONを扱うための組み込みAPIです。Codable(Encodable/Decodable)は、JSON、Property List、その他の形式への自動シリアライゼーションのためのモダンなSwiftプロトコルです。
struct User: Codable { let id: Int let name: String let email: String } let user = User(id: 1, name: "Alice", email: "alice@example.com") let encoder = JSONEncoder() let jsonData = try encoder.encode(user)
FlutterとReact Nativeには、独自の効率的なストレージライブラリがあります。
HiveはFlutter用の軽量で高速なキー値ストレージです。ネイティブコードを必要とせず(純粋なDart)、TypeAdapterによる型付けをサポートし、アイソレートで動作します。キャッシュ、設定、少量のデータに最適です。
ObjectBoxはFlutter、Android、iOS向けの高性能組み込みデータベースです。SQLiteより10倍以上高速で、オーバーヘッドを最小限に抑えるフラットファイル構造を使用します。リレーションシップ、クエリ、リアクティブサブスクリプション(ObjectBox Dart)をサポートします。
DriftはFlutterとDart向けのリアクティブSQLiteライブラリです。型安全なクエリ、マイグレーション、DAO関数、Streamサポート(リアクティブアップデート)を提供します。DriftはSQLiteを必要とするFlutterプロジェクトの主要な選択肢です。
よくある質問
プラットフォームによって異なります:Room(Android)はコンパイル時クエリチェック付きのSQLiteベースの公式ライブラリです。Core Data(iOS)はオブジェクトグラフを持つAppleのフレームワークです。クロスプラットフォームプロジェクトには、RealmまたはORM経由のSQLiteが適しています。
SharedPreferencesは同期アクセスとANRリスクがある古い実装です。DataStore(Jetpack)はKotlin CoroutinesとFlowに基づく現代的な代替品で、非同期、型付け、エラー保護をサポートしています。
Android:EncryptedSharedPreferencesまたはAndroid Keystore。iOS:WhenUnlockedThisDeviceOnlyアクセシビリティのKeychain Services。重要なデータには、生体認証とともにSecure Enclave(iOS)とハードウェアKeystore(Android)を使用します。
Cloud Firestoreは、リアルタイム同期、オフラインモード、自動スケーリングを備えたFirebaseのNoSQLデータベースです。チャット、ニュースフィード、デバイス間の同期が必要なプロジェクトに適しています。
Flutter:Hive(高速キー値)、Floor(SQLite ORM)、Drift(Moor、リアクティブSQLite)、ObjectBox(高性能組み込みDB)。React Native:Realm、WatermelonDB(遅延ロード)、AsyncStorage(SharedPreferencesの類似品)。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。