モバイルアプリにおけるRealm:その概要と仕組み

著者: IT Sectr 公開日: 2026-03-12 読了時間: 11 分

Realmは、iOSとAndroid向けにSQLiteやCore Dataの代替として開発されたモバイルオブジェクト指向NoSQLデータベースです。データはメモリ内のオブジェクトに直接アクセスできる独自形式で保存され、高い読み取り・書き込み速度を実現します。リアクティブ通知、Realm Syncによる自動同期、クロスプラットフォームデータモデルにより、Realmは10億台以上のデバイスで使用されています(MongoDBデータ、2025年)。

主要ポイント

  • Realmはメモリ内のデータに直接アクセスできるモバイルプラットフォーム向けNoSQLオブジェクトデータベースです。
  • Live Objects — Realmオブジェクトはデータ変更時に手動リロードなしで自動更新されます。
  • Zero-copy — データはアプリケーション層間でコピーされず、ORMのオーバーヘッドを排除します。
  • Realm Sync — MongoDB Atlas Device Syncを介したデバイス間の組み込み同期。
  • クロスプラットフォーム — データモデルはiOS、Android、Flutter、React Nativeで一度定義します。

Realmとは?

Realmは、モバイルアプリケーション専用に作られたオブジェクト指向データベースです。SQLiteとは異なり、RealmはSQLやリレーショナルモデルを使用しません。データはライブオブジェクト(Live Objects)として保存され、中間ORM層なしで直接アクセスできます。開発者は通常の言語オブジェクト(Swift、Kotlin、Dart)を操作するだけで、自動的にデータベースに保存されます。

Realmは2014年にスタートアップRealm Inc.として登場し、2019年にMongoDB Inc.に買収されました。それ以来、RealmはMongoDB Realmとして開発されています。これはモバイルデータ同期のための統合プラットフォームAtlas Device Syncの一部です。基本のローカルRealmデータベースは無料でオープンソース(Apache 2.0ライセンス)のままですが、Realm Sync(クラウド同期)はサブスクリプションで提供されます。

MongoDB Developer Report(2025年)によると、Realmは主要なローカルストレージとしてモバイルアプリケーションの15%で使用されています。主なユースケースは、オフラインモードのアプリケーション、複雑なオブジェクトモデル、デバイス間の同期が必要なアプリケーションで、Realmは開発速度とオブジェクト操作の容易さでSQLiteを上回ります。

Realmの原則

Live Objects — 各Realmオブジェクトはメモリマップドファイルを介してディスクにリンクされています。任意のスレッドでオブジェクトを変更すると、手動通知なしですべての他のスレッドに即座に反映されます。Realm通知を介してデータが変更されると、UIは自動的に再描画されます。Zero-copy — Realmはデータベースからオブジェクトにデータをコピーしません。オブジェクト自体がメモリ内のデータです。

Realmの仕組み:アーキテクチャとストレージ

RealmコアはC++で書かれており、データインデックスにB+ツリーを使用します。各行がリレーショナルテーブルのレコードであるSQLiteとは異なり、Realmはオブジェクトをグラフ構造のノードとして保存し、オブジェクト間の直接参照(前方ポインタ)を持ちます。オブジェクト間の関係は外部キーではなく直接ポインタであり、JOIN操作の必要性を排除します。

Realmファイル(.realm拡張子)はメモリマップドされています。OS自体がアクセスに応じてファイルページのメモリへのロードを管理します。これにより、Realmは利用可能なRAMより大きなデータベースを扱うことができ、RAMに収まるデータに対してはネイティブ言語データ構造(Swift ArrayやKotlin List)レベルの読み取りレイテンシを提供します。

Zero-copyとLive Objects

メモリマップドファイル — Realmの主要技術です。データベースファイルから言語オブジェクトにデータをコピーする代わりに(SQLiteがsqlite3_step + sqlite3_column_*で行うように)、Realmはデータベースファイルをプロセスのアドレス空間に直接マッピングします。言語オブジェクトはマップされたメモリ内のデータへの単なるポインタです。オブジェクトを変更すると、個別のsave呼び出しなしでディスク上のデータベースが変更されます。

特性Realm(zero-copy)SQLite(コピー)
読み取りメモリ直接アクセス(ナノ秒)オブジェクトにコピー(マイクロ秒)
書き込みメモリマップドファイルへの即時書き込みSQL INSERT/UPDATEトランザクションのsave()
関係直接ポインタ(前方ポインタ)外部キー + JOIN
メモリ消費ファイル + OSページキャッシュオブジェクト + SQLiteページキャッシュ
ライブオブジェクトあり(自動更新)なし(新しいfetchが必要)

メモリ消費は、アクティブな読み取り中はRealmの方が高くなります(ファイル全体または大部分がメモリにマップされます)が、書き込み操作中はオブジェクトコピーのメモリ割り当てが不要なため低くなります。モバイルデバイスで最大1GBのデータベースの場合、メモリマップドアプローチは中間コピーを行うSQLiteよりも全体的なパフォーマンスが優れています。

Realm vs SQLite vs Core Data:比較

SQLiteはSQLとACIDトランザクションを備えたリレーショナルDBMSです。Realmはメモリマップドアクセスを備えたオブジェクトNoSQLデータベースです。Core DataはSQLite上のAppleのORM層です。3つのアプローチにはそれぞれ適用分野と強みがあります。Realmは直接オブジェクトアクセス速度とリアクティビティに優れ、SQLiteは汎用性と成熟度、Core DataはAppleエコシステムとの統合に優れています。

Realmの読み取りパフォーマンスは、zero-copyアクセスによりSQLiteより10〜50%高くなっています。RealmはSQL解析が不要でメモリマップドページを直接変更するため、書き込みも高速です。ただし、Realmは大規模データベース(500MB超)を扱う場合、ファイルがアドレス空間に完全にマップされるため、より多くのRAMを消費する可能性があります。

基準RealmSQLiteCore Data
タイプNoSQLオブジェクトDBリレーショナルDBMS(SQL)SQLite上のORM
読み取り速度高速(zero-copy)中程度中程度(ORMオーバーヘッド)
リアクティビティLive Objects(組み込み)ラッパーが必要(Room/GRDB)NSFetchedResultsController
同期Realm Sync(MongoDB Atlas)カスタム実装が必要NSPersistentCloudKitContainer
プラットフォームiOS、Android、Flutter、RN、Node.jsiOS、Android、Web、デスクトップiOS/macOSのみ
ライブラリサイズ約4MB約600KBSDKに組み込み

RealmとSQLiteの選択は、多くの場合、優先順位に帰着します。開発速度とリアクティビティ(Realm)か、制御と汎用性(SQLite)か。Realmはデータモデルが頻繁に変更され、ライブUI更新を迅速に取得することが重要なMVPやプロトタイプに特に適しています。SQLite/Roomはデータ量が多く複雑な分析クエリを必要とする成熟した製品に適しています。

AndroidのRealm:Kotlin SDK

Realm Kotlin SDKはAndroid向けの公式ライブラリで、Kotlinで書かれています(Java SDKのラッパーではありません)。データモデルはRealmObjectを継承するクラスで定義され、一意の識別子には@PrimaryKeyアノテーションを使用します。Realm KotlinはKotlin Coroutines、Flow、およびコンパイル時コード生成のためのKSP(Kotlin Symbol Processing)をサポートしています。

RealmQueryはSQLなしでフィルタリングするための型安全なAPIを提供します。クエリはメソッドチェーンで構築します:queryfiltersortfind。結果はリスト(メモリにロード)またはFlow(データ変更時に更新されるリアクティブストリーム)として返せます。Realm Kotlinはネストされたオブジェクトとリスト(RealmList)もサポートしています。

Realm Kotlin SDKの例

データモデルRealmはRealmObjectインターフェースを実装するデータクラスとして定義されます。_idフィールドは一意の識別のために@PrimaryKeyでマークされます。1対多の関係はRealmList(他のRealmObjectのリスト)を介して実装されます。すべての書き込み操作(作成、更新、削除)はwriteトランザクションブロック内で実行されます。

kotlin
class Project : RealmObject {
    @PrimaryKey
    var _id: ObjectId = ObjectId().generate()
    var name: String = ""
    var tasks: RealmList<Task> = realmListOf()
}

class Task : RealmObject {
    @PrimaryKey
    var _id: ObjectId = ObjectId().generate()
    var title: String = ""
    var isComplete: Boolean = false
}

val config = Realm.Configuration.Builder(
    schema = setOf(Project::class, Task::class)
).build()

val realm = Realm.open(config)
realm.write { transactionRealm ->
    val project = copyToRealm(Project().apply {
        name = "Mobile App"
    })
    project.tasks.add(copyToRealm(Task().apply {
        title = "Design UI"
    }))
}

val projects: Flow<RealmResults<Project>> =
    realm.query<Project>()
        .sort(Project::name, Sort.ASCENDING)
        .asFlow()

Flowを返すクエリは、ProjectまたはTaskの追加、更新、削除など、Realm内のデータ変更時に自動的に新しい結果を発行します。FlowアプローチはComposeと完璧に調和します。ViewModelのcollectAsState()は、リストアダプターを手動で更新したりLiveDataを使用したりせずに、データ変更時に自動的にUIを再構成します。

iOSのRealm:Swift SDK

Realm Swift SDKは、async/await、Combine Publishers、Swift ConcurrencyをサポートするネイティブSwift APIを提供します。データモデルはObjectを継承するクラスとして定義され、プロパティには@Persistedを使用します。Realm Swiftは変更時に自動的にオブジェクトを更新し、通知(NotificationToken)を使用して個々のオブジェクトやコレクションの変更を購読できます。

@ObservedRealmObject@ObservedResultsは、Realmデータが変更されたときに自動的にViewを再描画するSwiftUI用のProperty Wrapperです。@ObservedResultsはクエリ結果で動作し、@ObservedRealmObjectは特定のオブジェクトで動作します。両方のプロパティはViewの初期化解除時に購読をキャンセルします。

Realm Swift SDKの例

SwiftUI統合はRealm SDKの強みの1つです。@ObservedResults Property WrapperはRealmクエリをSwiftUIの表示に結び付けます。タスクが変更されると、SwiftUIは自動的にリストを再構成します。realm.writeAsyncはUIをブロックせずにバックグラウンドスレッドでトランザクションを実行します。

swift
import RealmSwift

class TaskItem: Object, Identifiable {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var title: String = ""
    @Persisted var isDone: Bool = false
    @Persisted var priority: Int = 0
}

struct TaskListView: View {
    @ObservedResults(TaskItem.self,
        sortDescriptor: SortDescriptor(["priority"]))
    var tasks

    var body: some View {
        List {
            ForEach(tasks) { task in
                TaskRow(task: task)
            }
        }
        Button("Add Task") {
            let realm = try! Realm()
            try! realm.write {
                realm.add(TaskItem(value: ["title": "New task"]))
            }
        }
    }
}

@ObservedResultsはRealmクエリのライフサイクルを自動的に管理します。View作成時に変更の購読が作成され、破棄時にキャンセルされます。Property Wrapperはオプションの述語(NSPredicate)とソート記述子を受け入れます。これにより、手動でフェッチリクエストを記述したり、ViewModelを作成したり、Realm通知を購読したりする必要がなくなります。

Realmのユースケース

オフラインアプリケーション — Realmはインターネットなしでデータを利用可能にしなければならないシナリオに最適です。組み込み同期(MongoDB AtlasとのRealm Sync)はネットワーク接続時に自動的に競合を解決します。アプリはローカルデータで動作を続け、バックグラウンド同期は接続が利用可能になるとデータを更新します。

リアクティブインターフェース — Live ObjectsとFlow/Combine通知により、Realmは頻繁に更新されるデータを扱うアプリケーション(チャット、タスクフィード、共同ドキュメント)に便利な選択肢となります。手動でreloadDataやinvalidateを呼び出さなくても、データの追加、変更、削除時にUIが自動的に更新されます。

クロスプラットフォームプロジェクト — RealmはKotlin Multiplatform(KMP)、Flutter、React Native、Xamarinをサポートしています。データモデルは一度定義され、すべてのプラットフォームで使用されます。これによりコードの重複が減り、共通のビジネスロジックを持つiOSとAndroidアプリケーション間でスキーマの一貫性が保証されます。

Realm Sync:MongoDB Atlasを介した同期

Realm SyncはMongoDB Atlasに組み込まれたクラウドサービスです。アプリケーションはユーザーのデバイスとサーバー間でデータを自動的に同期します。競合は"last write wins"戦略またはサーバー上のカスタムConflict Resolution Functionsを使用して解決されます。Realm Syncはトラフィックを削減するための部分同期(データのサブセット)をサポートしています。

kotlin
class SyncRepository {
    private val app = App(
        AppConfiguration(
            appId = "my-realm-app-id"
        )
    )

    suspend fun syncData() {
        val user = app.login(Credentials.anonymous())
        val config = SyncConfiguration.Builder(
            user, setOf(Project::class)
        ).build()

        val syncedRealm = Realm.open(config)
        // 自動同期がアクティブです
    }
}

SyncConfigurationはMongoDB Atlasへの接続を構成し、同期するモデルのセットを定義します。ユーザー認証後、Realmは自動的にクラウドからデータをロードし、ローカルの変更とマージします。同期はバックグラウンドスレッドで実行され、手動呼び出しは不要です。SyncConfigurationを使用してRealmインスタンスを作成するだけです。

よくある質問

Realmは商用利用無料ですか?

はい、ローカルのRealmデータベースは完全に無料です(Apache 2.0ライセンス)。MongoDB Atlas経由のRealm Sync(クラウド同期)はAtlas Device Syncサブスクリプションに含まれる有料サービスです。無料のAtlasティアには、最初の500MBのデータと月間100万回の操作が含まれます。

SQLiteからRealmに移行できますか?

はい、移行はSQLiteからJSONにデータをエクスポートし、最初のアプリロード時にRealmにインポートすることで可能です。大量のデータの場合は、ストリーミング移行を使用してください。ユーザーが新しいアプリバージョンに移行する間、両方のデータベースに並行してデータを書き込み、その後SQLiteファイルを削除します。

Realmは同期競合をどのように処理しますか?

Realm Syncはデフォルトで"last write wins"戦略を使用します。最後の書き込みが前の書き込みを上書きします。複雑な競合の場合は、アプリケーションのビジネスロジックに従って異なるデバイスからの変更をマージするカスタムConflict Resolution FunctionsをMongoDB Atlasサーバーに設定します(例えば、置き換えではなく値のマージ)。

Realmは集計クエリをサポートしていますか?

RealmはデータベースレベルでSQL集計(SUM、AVG、GROUP BY)をサポートしていません。分析クエリの場合は、Realm Syncを介してRealmからMongoDB Atlasにデータをエクスポートし、MongoDB Aggregation Pipelineを通じて集計を実行することをお勧めします。単純なカウントの場合は、realm.query<T>().count()を使用してください。

Realmのデータは安全ですか?

Realmはデフォルトでデータを暗号化しません。暗号化するには、設定で64バイトの鍵を指定します:Realm.Configuration(encryptionKey: key)。暗号化はAES-256 + SHA-2 HMACを使用し、操作のオーバーヘッドが10〜20%増加します。暗号化なしでは、.realmファイルはファイルシステムにアクセスできる任意のプロセスで読み取ることができます。

まとめ

  • Realmは、モバイルアプリケーション向けのメモリマップドアクセス、ライブオブジェクト、クロスプラットフォームデータモデルを備えたオブジェクト指向NoSQLデータベースです。
  • Zero-copyアーキテクチャにより、言語オブジェクトにコピーせずにメモリマップドファイルから直接データを読み取ることができ、Realmは読み取りでSQLiteより10〜50%高速です。
  • Live Objectsと@ObservedResults(SwiftUI)/ Flow(Kotlin)は、手動データベースクエリなしでデータ変更時に自動UI更新を提供します。
  • Realm SyncとMongoDB Atlasは、"last write wins"戦略による競合解決を備えた組み込みクラウド同期を提供します。
  • クロスプラットフォームSDKはKotlin Multiplatform、Flutter、React Nativeをサポートし、データモデルは全プラットフォームで一度定義します。
  • 分析クエリに関しては、グループ集計がないためRealmはSQLiteに劣ります。複雑なレポートはMongoDB Aggregation Pipelineを通じて実行されます。
  • 推奨事項 — 頻繁なUI更新とクロスプラットフォーム同期が必要なオフラインアプリケーションにはRealmを、分析と安定したデータセットを扱うプロジェクトにはSQLite/Roomを使用してください。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください