NOTES / 笔记

小型独立 App 的轻后端架构

讨论以本地数据和平台同步能力支持小型个人应用的架构选择,也列出社区、交易与跨平台需求带来的边界。平台 API、费用与适用条件尚待技术审校。

文章目录

1. 背景

对于收藏管理、个人资产、习惯记录、家庭物品管理、学习资料整理等应用,核心数据通常具有以下特征:

  • 单用户使用;
  • 数据以私人内容为主;
  • 不需要用户之间互相关注、评论或交易;
  • 不需要维护统一的公共商品数据库;
  • 数据量相对有限;
  • 主要运行在 Apple 生态设备中;
  • 用户更关注隐私、离线可用、换机恢复和多设备同步。

这类产品如果沿用传统互联网应用架构,往往会引入大量不必要的复杂度:

  • 用户注册与登录;
  • 密码找回;
  • 服务端鉴权;
  • REST / GraphQL API;
  • 数据库部署;
  • 图片对象存储与 CDN;
  • 监控、告警和运维;
  • 数据合规与用户注销;
  • 服务端扩容与成本控制。

更合适的路线是:

Local-first + SwiftData/Core Data + CloudKit Private Database + StoreKit 2

它将本地数据库作为主数据源,将 iCloud/CloudKit 作为用户自己的远程存储、同步和恢复能力,从而省去大部分传统后端建设。


2. 总体架构

┌─────────────────────────────┐
│          SwiftUI UI         │
│  展示、编辑、搜索、筛选、统计 │
└──────────────┬──────────────┘
               │
┌──────────────▼──────────────┐
│     Domain / Application    │
│  用例、状态机、校验、导入导出 │
└──────────────┬──────────────┘
               │
┌──────────────▼──────────────┐
│   SwiftData / Core Data     │
│       本地数据库与缓存        │
└──────────────┬──────────────┘
               │
┌──────────────▼──────────────┐
│ CloudKit Private Database   │
│  数据同步、资源存储、换机恢复  │
└─────────────────────────────┘

补充能力:

StoreKit 2            → 会员、买断、订阅
Vision / Core ML      → 本地抠图、OCR、图片识别
FileExporter          → JSON / CSV / ZIP 导出
OSLog / Crash Reports → 日志与问题定位
App Intents / Widget  → 快捷录入、桌面小组件

3. 为什么不需要传统多用户后端

3.1 用户身份由 Apple ID 承担

如果每个用户只访问自己的数据,可以直接使用 CloudKit 的 Private Database。

逻辑上可以理解为:

当前 Apple ID
    └── 当前用户私有 CloudKit 数据库
          ├── 收藏夹
          ├── 收藏品
          ├── 标签
          ├── 图片
          └── 设置

开发者不需要再维护:

  • 用户表;
  • 登录状态;
  • Token;
  • 密码;
  • 手机验证码;
  • 邮箱验证;
  • 用户权限系统。

3.2 用户数据天然隔离

每个用户的数据位于自己的私有空间中,默认不对其他用户开放。

这特别适合:

  • 收藏柜;
  • 个人账本;
  • 习惯追踪;
  • 私人日记;
  • 家庭物品;
  • 个人知识卡片;
  • 游戏与阅读记录;
  • 保修和票据归档。

3.3 用户承担自己的 iCloud 存储

收藏照片、附件等资源可以通过 CloudKit Asset 或 iCloud 文件机制保存。

对于开发者而言,这意味着:

  • 不必购买对象存储;
  • 不必维护 CDN;
  • 不必按用户流量持续付费;
  • 用户增长不会线性增加服务器成本。

4. 建议的数据模型

以收藏管理类 App 为例:

CollectionCabinet
├── id
├── name
├── coverImage
├── sortOrder
├── theme
├── createdAt
└── updatedAt

CollectionItem
├── id
├── name
├── coverImage
├── galleryImages
├── purchasePrice
├── estimatedValue
├── purchaseDate
├── status
├── notes
├── cabinet
├── tags
├── createdAt
└── updatedAt

Tag
├── id
├── name
├── category
└── color

PurchaseRecord
├── id
├── deposit
├── balance
├── channel
├── orderDate
├── arrivalDate
└── item

对于模型收藏,还可以增加:

  • 品牌;
  • 产品线;
  • 作品;
  • 比例;
  • 类型;
  • 版本;
  • 拼装状态;
  • 包装状态;
  • 摆放位置;
  • 配件完整度;
  • 是否限定;
  • 是否已售。

5. 本地优先的设计原则

5.1 本地数据库是真正的主入口

所有增删改查应首先写入本地数据库,UI 直接观察本地状态。

用户操作
→ 本地立即保存
→ UI 立即更新
→ 系统后台同步 CloudKit

好处:

  • 无网可用;
  • 操作即时;
  • 弱网下体验稳定;
  • 不依赖服务端接口延迟;
  • 云同步失败时不会阻塞主要流程。

5.2 云端是同步层,不是每次请求的唯一数据源

不应设计成:

打开页面
→ 请求服务器
→ 等待返回
→ 才能展示

而应设计成:

打开页面
→ 读取本地数据库
→ 立即展示
→ 后台完成增量同步

6. iCloud 可以作为付费卖点

免费版可以提供

  • 本地保存;
  • 基础录入;
  • 少量收藏品数量;
  • 基础展柜;
  • 基础搜索;
  • 单设备使用。

Pro / 永久版可以提供

  • iCloud 多设备同步;
  • 换机自动恢复;
  • 收藏数量不限;
  • 多图与高清图片;
  • 高级统计;
  • 批量操作;
  • 高级主题;
  • JSON / CSV 导出;
  • 自定义字段;
  • 小组件;
  • AI 辅助录入。

对用户的表达不应停留在技术术语,而应强调结果:

  • 无需注册账号;
  • 数据保存在自己的 iCloud;
  • 换机自动恢复;
  • iPhone、iPad、Mac 同步;
  • 开发者无法查看私人数据;
  • 即使断网也可正常使用。

7. 仍然不能忽视的技术难点

CloudKit 能替代传统服务器,但不代表没有工程复杂度。

7.1 同步状态

需要处理:

  • 用户未登录 iCloud;
  • iCloud Drive 关闭;
  • iCloud 空间不足;
  • 弱网或离线;
  • 多设备同时编辑;
  • 删除操作同步;
  • 同步延迟;
  • 部分资源下载失败;
  • 首次全量同步。

建议在 UI 中提供明确状态:

已同步
同步中
等待网络
iCloud 未登录
存储空间不足
同步失败

7.2 冲突处理

需要明确不同字段的冲突策略:

  • 最后写入优先;
  • 按字段合并;
  • 保留副本;
  • 用户手动选择;
  • 删除优先还是修改优先。

对于收藏类 App,很多记录不会高频并发修改,可以采用较简单的策略,但不能完全忽略。

7.3 数据模型迁移

App 更新后,常见变化包括:

  • 新增字段;
  • 字段改名;
  • 枚举调整;
  • 关系变化;
  • 图片存储方式变化。

这要求:

  • 版本化数据模型;
  • 向后兼容;
  • 灰度迁移;
  • 失败回滚;
  • 迁移前备份。

7.4 图片资源管理

图片是成本和 Bug 的主要来源之一。

建议考虑:

  • 原图压缩;
  • 缩略图;
  • HEIC / JPEG;
  • 图片方向;
  • 自动抠图缓存;
  • 本地缓存淘汰;
  • CloudKit Asset;
  • 删除后的资源清理;
  • 多设备按需下载;
  • 重复图片去重;
  • 低存储空间处理。

8. iCloud 同步不等于备份

这是必须区分的概念。

同步

设备 A 删除
→ CloudKit 同步删除
→ 设备 B 也删除

备份

当前数据
→ 导出不可变文件
→ 可独立保存和恢复

因此专业版本仍应提供:

  • JSON 完整备份;
  • CSV 数据导出;
  • 图片 ZIP 打包;
  • 备份文件导入;
  • 定期导出提醒;
  • 数据迁移说明。

用户的数据不能只存在于 App 无法直接访问的私有格式中。


9. 什么场景不适合这套架构

一旦产品需要以下能力,就不能只依赖 CloudKit Private Database:

  • 用户之间互相关注;
  • 公开内容流;
  • 点赞和评论;
  • 多人协作;
  • 公共商品数据库;
  • 跨用户搜索;
  • 交易撮合;
  • Web、Android 和 Apple 多端统一账户;
  • 管理后台;
  • 内容审核;
  • 推荐系统;
  • 公共排行榜;
  • 服务端 AI 推理;
  • 大规模实时协作。

此时仍然需要真正的业务后端。


10. 适合复用的产品类型

这套架构适合以下“小而美”工具:

  • 模型与玩具收藏;
  • 游戏收藏和通关记录;
  • 图书、电影、唱片收藏;
  • 家庭物品与保修管理;
  • 个人设备资产管理;
  • 证书和资质管理;
  • 私人项目档案;
  • 灵感素材库;
  • 旅行纪念品;
  • 票根和纪念册;
  • 家庭库存;
  • 个人课程和学习资料柜;
  • 宠物成长记录;
  • 植物养护记录;
  • 个人运动器材管理。

11. 可复用技术底座

可以先建立一套通用 App Starter:

SwiftUI
+ SwiftData
+ CloudKit
+ StoreKit 2
+ 图片压缩与缓存
+ JSON/CSV 导入导出
+ 会员权限控制
+ iCloud 状态检测
+ 日志与崩溃收集
+ 隐私声明模板

后续新产品只替换:

  • 领域数据模型;
  • 录入表单;
  • 首页视觉;
  • 统计维度;
  • 标签体系;
  • 品类特有状态机。

这样可以降低每个小应用的边际开发成本。


12. 核心结论

对于单用户、私有数据、Apple 生态内的小型工具,最佳路线往往不是“再造一个 SaaS”,而是:

本地优先,iCloud 同步,无账号体系,无自建后端,买断或订阅解锁高级能力。

它的优势不是技术最先进,而是:

  • 开发范围可控;
  • 固定成本低;
  • 用户隐私强;
  • 服务器成本低;
  • 可离线使用;
  • 容易做永久买断;
  • 适合独立开发者持续迭代。

但必须守住边界:

一旦进入社区、交易、公共数据库和跨平台账户体系,这套轻架构的优势就会迅速消失。