モバイル開発におけるキャッシュとデータ同期:概要、戦略、仕組み

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

モバイル開発において、データの処理、キャッシュ、同期は、アプリケーションのパフォーマンスと信頼性を決定する3つの重要な側面です。Google Android Architecture Guideによると、適切なデータ処理アーキテクチャは応答速度とユーザーエクスペリエンスに直接影響します。Repositoryパターンは、すべてのデータソースへの単一のアクセスポイントを提供します。

重要ポイント

  • Repository — RemoteおよびLocal Data Sourceの実装詳細を隠蔽する単一のデータソース
  • LRU Cache — 制限に達したときに最も長く使用されていないアイテムを追い出すキャッシュアルゴリズム
  • Offline Queue — デバイスがオフラインのときに操作を遅延実行する仕組み
  • Conflict Resolution — 複数デバイス間の同期時の競合を解決する戦略
  • Schema Migration — データを失わずにローカルデータベース構造を安全に変更するプロセス

モバイルアプリケーションにおけるデータ処理:RepositoryパターンとData Source

Repositoryパターンは、単一のリポジトリクラスがすべてのデータ操作を管理し、リモートREST APIやローカルストレージ(RoomまたはSwiftData)を抽象化するアーキテクチャアプローチです。このデータ処理方法により、アプリケーションは最初にMemory CacheまたはDisk Cacheから情報を取得し、次にネットワークから取得することで、応答時間を短縮します。モバイル開発では、GoogleとAppleの推奨により、Repositoryが事実上の標準となっています。

Remote Data SourceとLocal Data Source

Remote Data SourceはHTTPリクエストを介してサーバーから最新情報を提供します。Local Data Sourceはデバイス上のローカルストレージで、AndroidではRoom、iOSではSwiftDataを介して実装されます。リポジトリは両方のソースを組み合わせます。最初にローカルキャッシュを確認し、データがない場合はリモートAPIにリクエストします。このデータ処理の構成により、アプリケーションはオフラインモードで機能し、サーバー負荷を軽減できます。

KotlinのRepository例

kotlin
class UserRepository(
    private val remoteDataSource: UserRemoteDataSource,
    private val localDataSource: UserLocalDataSource
) {
    suspend fun getUsers(): List<User> {
        localDataSource.getCachedUsers()?.let { return it }
        val users = remoteDataSource.fetchUsers()
        localDataSource.cacheUsers(users)
        return users
    }
}

SwiftのRepository例

swift
class UserRepository {
    private let remote: UserRemoteDataSource
    private let local: UserLocalDataSource
    
    func getUsers() async throws -> [User] {
        if let cached = await local.getCached() { return cached }
        let users = try await remote.fetch()
        await local.save(users)
        return users
    }
}

データキャッシュ:LRU Cache、Disk Cache、Memory Cache

LRU Cache(Least Recently Used)は、制限に達したときに最も長くアクセスされていない要素を削除するキャッシュアルゴリズムです。モバイルアプリケーションでは、LRU Cacheは画像、API応答、シリアライズされたオブジェクトに使用されます。適切なデータキャッシュにより、ネットワークリクエストの数が減り、コンテンツの読み込みが高速化します。モバイルアプリケーションにおけるキャッシュは、高性能のための必須コンポーネントです。

Memory Cache vs Disk Cache

Memory CacheはRAMにデータを保存します — アクセスは非常に高速ですが、容量はアプリケーションのヒープサイズによって制限されます。Disk Cacheはファイルシステムに情報を保存します — 低速ですが、より多くのデータを保持でき、セッション間で持続します。モバイル開発における最適な戦略は2層キャッシュです:ホットデータ用のMemory Cacheとコールドデータ用のDisk Cacheです。データを処理する際、最初にメモリ内の第1層キャッシュがチェックされ、次にディスク上の第2層キャッシュがチェックされます。

LRU Cache実装例

kotlin
class MemoryCache<K, V>(
    private val maxSize: Int = 100
) {
    private val cache = LinkedHashMap<K, V>(0, 0.75f, true)

    fun get(key: K): V? = cache[key]

    fun put(key: K, value: V) {
        if (cache.size >= maxSize) {
            cache.remove(cache.keys.first())
        }
        cache[key] = value
    }
}

キャッシュ無効化戦略

TTLキャッシュ(Time To Live)は指定された時間間隔後に自動的にエントリを削除します — APIデータに適しています。イベント駆動型無効化は、変更に関するプッシュ通知を受信したときにキャッシュをクリアします。モバイルアプリケーションでは、キャッシュ戦略の選択はデータタイプによって異なります:画像は長期間キャッシュされますが、ニュースフィードは頻繁な無効化が必要です。AndroidのCoilとiOSのKingfisherは、画像を扱うためにLRU Cacheを既に組み込んでいます。

オフラインキュー:Offline QueueとSync Manager

Offline Queueは、デバイスがオフラインのときにユーザー操作(作成、更新、削除)をローカルデータベースに保存するデータ構造です。接続が回復すると、Sync Managerがこれらの操作をサーバーに順次適用します。このタイプのデータ同期により、一時的なネットワーク損失中に変更が失われることがありません。モバイル開発では、Offline Queueは不安定な接続のアプリケーションにとって重要なコンポーネントです。

Offline Queueのアーキテクチャ

キューはRoomまたはSwiftDataのテーブル上に構築され、フィールド:操作タイプ、JSONリクエスト本文、タイムスタンプ、ステータスを持ちます。Sync Managerは、保留中の操作を処理し、サーバーに送信し、ステータスを更新し、成功したエントリを削除するバックグラウンドサービスです。AndroidのWorkManagerやiOSのBGTaskSchedulerを介したデータ同期は、デバイスの再起動後も継続します。適切なデータ処理とOffline Queueを組み合わせることで、シームレスなユーザー体験が保証されます。

KotlinのOffline Queue例

kotlin
@Entity
data class SyncOperation(
    @PrimaryKey val id: Long,
    val endpoint: String,
    val method: String,
    val body: String,
    val createdAt: Long
)

class SyncManager(
    private val dao: SyncOperationDao,
    private val api: ApiService
) {
    suspend fun syncPending() {
        dao.getPendingOperations().forEach { op ->
            try {
                api.execute(op.endpoint, op.method, op.body)
                dao.delete(op.id)
            } catch (e: Exception) {
                // retry on next cycle
            }
        }
    }
}

再試行ポリシーとタイムアウト

再試行間の指数バックオフ(1秒、2秒、4秒、8秒)は、サーバーを雪崩負荷から保護し、無限再試行を防ぎます。5回の試行制限により、キューのオーバーフローを防ぎます。サーバー側の冪等性サポートを備えたモバイルアプリケーションでのデータ同期により、重複を避けながら安全な再試行が可能です。これは金融取引や注文にとって特に重要です。

データ同期:Conflict ResolutionとSchema Migration

Conflict Resolutionは、同じデータが異なるデバイスで同時に変更される状況のための戦略セットです。基本的なデータ同期では、アプローチの選択が必要です:Last-Write-Wins(最後の書き込みが勝ち)、バージョニング(より高いバージョンが勝ち)、または手動解決です。複雑なシナリオでは、データの数学的収束を保証するCRDT(Conflict-Free Replicated Data Types)が使用されます。

競合解決戦略

Last-Write-Winsは実装が最も簡単ですが、ユーザーの変更を失う可能性があります。Version Vector — 各レコードはバージョン番号とデバイス識別子を保存し、バージョンが一致しない場合に競合が発生します。CRDTは最も信頼性が高いが複雑な戦略です:データは中央調整者なしで数学的に単一状態に収束します。CRDTに基づくモバイルアプリケーションのデータ同期は、Google Docsの共同編集やNotionのノート同期で使用されています。

Schema Migration:安全なデータベース更新

アプリケーションが更新されると、ローカルデータベース構造が変更されます:カラム、テーブル、インデックスが追加されます。Schema Migrationは、データを失わずに既存のデータベースを新しいスキーマに変換するプロセスです。Roomは古いバージョンと新しいバージョンを持つMigrationクラスを通じてマイグレーションをサポートします。SwiftDataは変更を記述するためにVersionedSchemaを使用します。アプリケーションバージョン間の適切なデータ同期には、マイグレーションが冪等にテストされる必要があります。

RoomでのSchema Migration例

kotlin
val migration1to2 = object : Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("ALTER TABLE users ADD COLUMN avatar_url TEXT")
    }
}

@Database(
    entities = [User::class],
    version = 2
)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

SwiftでのConflict Resolution例

swift
enum ConflictStrategy {
    case lastWriteWins
    case versionVector
    case crdt
}

struct VersionedDocument {
    let id: String
    let version: Int
    let data: Data
    let editedBy: String
    
    func resolve(with remote: VersionedDocument) -> VersionedDocument {
        return version >= remote.version ? self : remote
    }
}

ローカルストレージのためのRoomとSwiftData

RoomはAndroid向けのGoogleのローカルストレージライブラリで、SQLite上に構築され、宣言的なクエリ記述のためのアノテーションを提供します。SwiftDataはiOS、macOS、watchOS、visionOS向けのAppleのフレームワークで、簡潔なSwift Macro構文を持つCore Dataの後継です。両方のツールはデバイス上のデータ処理の課題を解決しますが、コード構成に対するアプローチが異なります。モバイルアプリケーションのキャッシュは、多くの場合、これらの技術上に構築されます。

Room:DAO、Entities、Type Converters

Roomはテーブルに@Entityアノテーション、クエリに@Daoを使用します。DAOはコンパイル時チェックですべてのSQL操作をカプセル化し — SQL構文エラーは実行前に検出されます。Type Converterは複合型(Date、List)をSQLiteプリミティブに変換します。Androidアプリケーションにおける現代的なデータ処理はRoom + Flowを中心に構築され、キャッシュまたはローカルデータベースの変更時にリアクティブなUI更新を提供します。

SwiftData:@Modelと@Query

SwiftDataはエンティティを定義するためにマクロ@Modelを、データを監視するために@Queryを使用します。フレームワークは自動的に依存関係を追跡し、変更時にインターフェースを更新します。スキーママイグレーションはすべてのバージョンを記述するVersionedSchemaを使用します。SwiftDataとサーバー間のデータ同期は、@Queryを介して更新を購読するカスタムSync Managerを通じて実装されます。

SwiftDataのモデル例

swift
@Model
final class UserModel {
    var id: String
    var name: String
    var email: String
    var updatedAt: Date
    
    init(id: String, name: String, email: String) {
        self.id = id
        self.name = name
        self.email = email
        self.updatedAt = Date()
    }
}

Room vs SwiftDataの比較

基準RoomSwiftData
プラットフォームAndroidApple(iOS、macOS、visionOS)
基盤SQLiteSQLite(Core Dataスタック)
構文KotlinアノテーションSwift Macro
マイグレーションMigrationクラスVersionedSchema
リアクティビティFlow / LiveData@Queryプロパティラッパー
クロスプラットフォームAndroidのみAppleのみ

よくある質問

LRU Cacheとは?

LRU Cacheは、制限に達したときに最も長く使用されていないアイテムを削除するキャッシュアルゴリズムです。モバイルアプリケーションでは画像やAPIデータに使用されます。

Offline Queueの仕組みは?

Offline Queueはネットワークがないときにユーザー操作をローカルデータベースに保存します。Sync Managerは接続が回復したときにそれらを実行し、変更がサーバーに配信されることを保証します。

Conflict Resolutionとは?

Conflict Resolutionはデータ同期中の競合を解決する戦略です。主なアプローチ:分散システム向けのLast-Write-Wins、Version Vector、CRDT。

RoomかSwiftDataか — どちらを選ぶべき?

AndroidにはRoomを選択 — コンパイル時SQL検証を備えた成熟したライブラリです。iOSには宣言的構文のSwiftDataを。クロスプラットフォームプロジェクトにはSQLDelightやRealmが適しています。

同期はどのくらいの頻度で行うべき?

最適なデータ同期は、重要な操作では変更のたびに、その他では15〜30分ごとにバックグラウンドで行います。即時配信にはプッシュ通知を使用します。

まとめ

  • RepositoryはRemoteとLocal Data Sourceを組み合わせ、データ処理時に単一のアクセスポイントを提供する
  • LRU Cacheは2層のMemory + Disk Cacheシステムでネットワークリクエストを削減しコンテンツ読み込みを高速化する
  • Offline QueueとSync Managerは一時的な接続損失中の変更配信を保証する
  • Conflict Resolution(Version VectorまたはCRDTベース)は並列同期中のデータ損失を防ぐ
  • Schema Migrationはユーザーデータを失わずに安全なローカルデータベース更新を保証する
  • Room(DAO)とSwiftData(@Model)はモバイル開発におけるローカルストレージの標準ソリューション
  • キャッシュとデータ同期への包括的アプローチが高性能モバイルアプリケーションの基盤である

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

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

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