メインコンテンツへスキップ
公開中

サーバーを持たないiOSアプリ — 記録を端末に閉じ、機種変更は暗号化ファイルで渡す

SQLiteの端末内マイグレーション、CryptoKitによるAES-256-GCMのバックアップ、買い切り課金の二重ゲート。あとから御朱印帳の設計記録

撮りためた御朱印を整理するiOSアプリ「あとから御朱印帳」

iOS版を App Store で公開しています(2026年9月公開・基本無料、買い切りの追加機能あり)。

あとから御朱印帳を App Store でダウンロード

なぜポートフォリオにあるか

個人向けのアプリでいちばん高くつくのは、サーバーです。月額が積み上がるだけでなく、止め方まで含めて運用し続けなければならない。あとから御朱印帳は自前のサーバーを1台も持たずに本番配信し、そのかわりに記録・機種変更・課金を端末の中だけで完結させる設計を選びました。

なぜ作ったか

御朱印帳を何冊も持っていると、いただいた御朱印の記録が追いつかなくなります。写真は撮ってある。けれど、どの寺社でいつ参拝したのかを後から整理する手段がない。

既存の御朱印アプリへの不満を調べると、★1の最大の理由は「会員登録が必要」と「広告」でした。そこで、アカウントを作らせない・広告を出さない・データを自分のサーバーに預からせない、という3つを最初に決めました。3つ目を守るいちばん確実な方法は、サーバーを持たないことです。

いちばん難しかったこと

サーバーがないと、サーバーがやってくれていたことを全部、端末の中でやる必要があります。

  1. 機種変更。 同期がないので、記録を新しい端末へ運ぶ手段を自分で用意しなければならない。しかも運ぶファイルには参拝の記録と写真が入っています。
  2. スキーマの変更。 サーバーなら一度マイグレーションすれば終わりますが、端末のデータベースは利用者ごとに別の世代で止まっています。どの世代からでも最新まで上げられないといけない。
  3. 課金の解放。 サーバー側で権利を確認できないので、画面の抜け道がそのまま無料開放になります。

どう決めたか(と、捨てたもの)

アプリは自前のサーバーと通信しない、を仕様ではなくテストにしました。アプリのコード・モジュールに fetch / XMLHttpRequest / WebSocket の経路が無いことを、アーキテクチャテストが静的に検査します。書かないつもり、ではなく、書いたらCIが落ちます。

暗号化は自分で実装しないと決めました。JavaScript の暗号実装は監査できず、サイドチャネルの保証もありません。そこで Swift のネイティブモジュールを書き、OS の CryptoKit と CommonCrypto を呼んでいます。

捨てたものは同期・共有・複数端末・Web版です。代償もはっきりしています。バックアップのパスフレーズを失えば、誰にも復元できません。運営者にもです。

実際に動いているもの

バックアップは独自の .goshuin 形式です。鍵は PBKDF2-HMAC-SHA256 を60万回(OWASP 2023 の推奨値)回して作り、中身はチャンクごとに AES-256-GCM で暗号化します。45バイトのヘッダ全体を全チャンクの追加認証データに入れているので、反復回数やチャンク長を書き換えると復号の時点で認証に失敗します。平文の長さも照合するので、末尾を切り落とされても検出できます。

課金は、1回払いの買い切り1本と、3つの機能ゲート(2冊目の御朱印帳・写真のまとめて振り分け・PDF/CSV の書き出し)だけです。解放条件は画面とサービス層の2箇所で判定し、サービス層でも条件を満たさない呼び出しをエラーとして拒否します。画面側の判定漏れが、そのまま無料開放につながらないようにするためです。ただし判定はすべて端末の中なので、改造された端末まで防げるわけではありません。

構成はポート&アダプタで、合成点は1箇所です。SQLite と暗号のアダプタを差し替えれば、ドメイン層をシミュレータなしで Jest から動かせます。

なお、不具合の報告とアプリの使われ方の計測は既定でオンにしています(設定から止められます)。記録の中身は送りません。

コードから数えられる値

2026-09-08 から 09-25 までの158コミット(マージを除く)。設計判断の記録(ADR)が40本あり、採用しなかった案と、決定を撤回する条件まで書いてあります。

テストは429ファイル。加えて実機を操作する Maestro の E2E が11フロー(番号つきの本体フロー。共通の部品フローは除く)。端末内の SQLite は6世代のマイグレーションを持ち、どの世代からでも最新まで上げられます。

アプリの表示名・LP・App Store の掲載文は14言語で出しています。固定費は Apple Developer Program の年会費と LP のドメイン代だけで、どちらも止め方は「更新しない」です。

これは、あなたの案件の何を証明するか

「個人情報をサーバーに預からない」は、仕様書に書くだけなら簡単です。それをテストで破れない約束にするところまでやった実例です。医療・子ども・日記・資産管理のように、預からないこと自体が価値になるアプリでは、この構成がそのまま使えます。

サーバーを持たないことは、運用費だけでなく、法令や審査で説明しなければならない論点も減らします。一方で、同期やバックアップ、課金の確認を端末の中で組む必要があり、そこが腕の見せどころになります。

端末内 SQLite のマイグレーション・暗号化バックアップ・StoreKit 2 の買い切り課金は、コードつきでExpo でサーバーなしのオフライン iOS アプリを設計する解説記事にまとめました。

オフライン前提のモバイルアプリは、モバイルアプリ開発のサービスとしてお請けしています。

コードから数えられる値

設計判断の記録(ADR)
40本採択日・改訂履歴・撤回条件つき。サーバーを持たない判断そのものも ADR として残している
テスト
429ファイルドメイン層はシミュレータなしで Jest から検証。加えて実機操作の E2E(Maestro)が11フロー
端末内のスキーマ移行
6世代SQLite のスキーマを端末上で積み上げる。サーバー側で一括移行する手段は存在しない
掲載言語
14言語アプリの表示名・LP・App Store の掲載文

よくある質問

あとから御朱印帳はどこでダウンロードできますか?
iOS版を App Store で公開しています(2026年9月公開)。基本機能は無料で、2冊目の御朱印帳やまとめて振り分け、PDF/CSV の書き出しは買い切りの追加機能です。Android版はありません。
記録や写真はどこに保存されますか?
端末の中だけです。アプリは自前のサーバーと通信せず、アプリのコードに通信経路が無いことをアーキテクチャテストで静的に検査しています。不具合の報告と利用状況の計測は既定でオンですが、記録の中身は送りません。
機種変更したら記録はどうなりますか?
iOS 標準のバックアップに加えて、`.goshuin` 形式の暗号化バックアップファイルで引き継げます。鍵は PBKDF2-HMAC-SHA256 を60万回回して作り、中身は AES-256-GCM で暗号化します。パスフレーズを失うと誰にも復元できません。
会員登録やログインは必要ですか?
必要ありません。アカウントの仕組み自体を持っていません。既存アプリへの不満で最も多かったのが会員登録だったため、最初に外した機能です。
サーバーを持たないのに、課金はどう守っていますか?
App Store の購入情報を端末で確認し、解放条件を画面とサービス層の2箇所で判定しています。サービス層でも条件を満たさない呼び出しを拒否するので、画面側の判定漏れがそのまま無料開放にはなりません。判定は端末内で完結するため、改造された端末まで防ぐ設計ではありません。

あとから御朱印帳を使ってみる

iOS版を App Store で公開しています(2026年9月公開・基本無料、買い切りの追加機能あり)。

あとから御朱印帳を App Store でダウンロード

同様の課題、抱えていませんか?

あなたのビジネス課題も、最新の技術で解決できます。 まずは30分の無料技術相談から、状況をお聞かせください。

自社の課題もSaaS化できるか相談する

プロジェクト単位(請負)・技術顧問、どちらにも対応可能です

自社プロダクト一覧を見る