解こうとしたこと
店を探すときに一番効くのは、知らない誰かの星 3.5 ではなく、友達の「あそこ良かったよ」です。ところが既存の口コミサービスは不特定多数のレビューを集める方向にしか作られていません。
評価の総量ではなく、評価者が誰かのほうが重要な場面がある。そこだけを切り出したアプリにしています。
サーバを持たないことにした
最初の版は、Web フロントとサーバ、データベース、認証、決済を別々のサービスで組んだ構成でした。動きはしましたが、身内向けのアプリに対して支える対象が多すぎました。使われていない時間にも費用と保守が発生し続けます。
全部やめて、Apple の CloudKit だけに寄せる形で書き直しました。データの置き場も、認証も、画像の配信も Apple 側に預けます。自分で運用するサーバはゼロになり、動いている限り費用もかかりません。
個人で長く続けるつもりのものは、作る速さより畳まずに済むかどうかで決まります。ここは機能を足す判断ではなく、支えるものを減らす判断でした。
使う仕組みの制約に、データの形を合わせる
CloudKit は自由に検索できるデータベースではありません。項目ごとに索引を張らないと条件で引けず、その設定は管理画面から手で入れる必要があります。設定漏れが即障害になる形は避けたいところでした。
そこで、検索に頼らなくても辿れるようにデータを持たせています。グループが持つ店の一覧、ユーザーが入っているグループの一覧、といった具合に、関係する相手の ID を配列で抱えておき、そこから直接引く。索引の有無に関わらず、同じ経路で必ず取得できます。
店の情報は Apple の地図が付ける識別子を鍵にしています。同じ店を別々の人が登録しても、自然に 1 つにまとまります。
強制できないことを、正直に扱う
グループには承認制の設定があります。ただしこの承認は、サーバ側で完全に強制することができません。CloudKit の権限の粒度では、参加者の一覧を書き換える操作をアプリの外から防ぎきれないためです。
その気になれば、承認を通さずに参加することは技術的に可能です。この事実は隠さず設計文書に書いてあります。書いておかないと、後から見た人が「守られている」と誤解したまま、その前提で別の機能を積んでしまう。
実際の運用は、アプリ上の導線と身内という関係性、それに通報の仕組みで担保しています。技術で守れる範囲と、そうでない範囲を分けて把握しておくこと自体が、この構成を選んだ責任だと思っています。