個人的体験から始めた、思い出共有フォトアルバムアプリの技術設計
はじめに
この記事は、個人的な体験をきっかけに作り始めた
「思い出を大切な人と共有するフォトアルバムアプリ」 について、
- なぜこの技術構成にしたのか
- なぜ最初から共有機能を作らなかったのか
- 個人開発として何を優先したのか
といった 設計・技術選定の観点 をまとめたものです。
背景や思想については note に別途まとめているため、
ここでは エンジニア向けに技術面を中心 に書いていきます。
※ 本記事は、以下のnote記事で書いた内容を前提に、
技術設計・実装判断にフォーカスしています。
(背景や思想についてはnote側をご覧ください)
このアプリの前提条件(技術要件)
最初に、このアプリを作る上での前提条件を整理しました。
- 不特定多数向けの SNS ではない
- ユーザーは家族・友人などの小規模コミュニティ
- 写真データを安全に扱えること
- 個人開発でも無理なく運用できること
- 将来的に共有機能を追加できる拡張性
この前提から、
「フルスクラッチで全部作らない」
という判断を早い段階でしています。
技術スタック概要
現在の構成は以下です。
- フロントエンド:React(Next.js)
- 認証・DB・Storage:Supabase
- デプロイ:Vercel
個人開発でありながら、
「安心して写真を預けられる」体験を実現するために、
マネージドサービスを積極的に採用しています。
Supabase を選んだ理由
認証(Auth)
このアプリでは、
「ログインして初めて、自分専用の空間を持つ」
という体験を重視しています。
Supabase Auth を使うことで、
- メール認証がすぐに使える
- 実装コストが低い
- セキュリティを自前で考えすぎなくていい
というメリットがありました。
個人開発で「認証を自作しない」判断は、
結果的にプロダクトの質を上げてくれています。
データベース(PostgreSQL + RLS)
Supabase は PostgreSQL ベースで、
RLS(Row Level Security) を前提に設計できます。
これにより、
- 「このユーザーはこのアルバムにアクセスできるか」
- 「この写真は誰のものか」
といった制御を、
アプリケーションコードではなく DB 側で担保できます。
将来的に共有機能を実装する場合も、
- album_members テーブルを追加
- RLS ポリシーを調整
といった形で拡張できる想定です。
RLS(Row Level Security)の具体例
Supabase を採用した大きな理由のひとつが、
RLSを前提にしたデータ設計ができる点です。
たとえば、アルバムテーブルでは
「ログインしているユーザー本人だけが、自分のアルバムにアクセスできる」
という制御を、以下のようにデータベース側で定義しています。
-- RLS を有効化
ALTER TABLE albums ENABLE ROW LEVEL SECURITY;
-- 自分のアルバムのみ参照可能
CREATE POLICY "Users can view their own albums"
ON albums
FOR SELECT
USING (auth.uid() = user_id);
-- 自分のアルバムのみ作成可能
CREATE POLICY "Users can insert their own albums"
ON albums
FOR INSERT
WITH CHECK (auth.uid() = user_id);
-- 自分のアルバムのみ更新・削除可能
CREATE POLICY "Users can update their own albums"
ON albums
FOR UPDATE
USING (auth.uid() = user_id);
このように、
「誰がどのデータにアクセスできるか」を
アプリケーションコードではなくデータベースで保証できるため、
- API 実装がシンプルになる
- セキュリティ事故のリスクを下げられる
- 将来的な共有機能の拡張もしやすい
といったメリットがあります。
※ 本記事のコードは一例であり、実際の要件に応じてポリシー設計は調整してください。
Storage(写真管理)
写真データは Supabase Storage を利用しています。
理由はシンプルで、
- Auth と連携しやすい
- パス設計でユーザー単位管理ができる
- 将来的なアクセス制御がしやすい
からです。
AWS S3を直接APIで操作する構成にしなかったのも、
個人開発としての運用コストを下げる判断でした。
採用しなかった選択肢
-
Firebase
→ NoSQL前提で、RLS的な考え方が合わなかった -
フルスクラッチ(Auth + S3 + API)
→ 個人開発では、保守コストが体験価値を下げると判断
Vercel を選んだ理由
Vercel を選んだ理由は、
「考えることを減らすため」 です。
- GitHub 連携で即デプロイ
- 環境変数管理が楽
- Next.js との相性が良い
個人開発では、
インフラを触っている時間 = ユーザー体験が良くなる時間
とは限らないため、
フロントエンドに集中できる環境を優先しました。
なぜ最初から共有機能を作らなかったのか(設計判断)
技術的には、
最初から「家族共有」機能を作ることも可能でした。
ただ、あえて次の順番にしています。
- 一人で安心して使える
- 思い出を整理できる
- 共有はその延長線上
理由は、
- 共有は設計が一気に複雑になる
- 本当に必要な共有の形は、使ってみないと分からない
- まずは「個人の体験」を完成させたかった
からです。
これは技術的制約ではなく、
プロダクト設計としての判断です。
設計上の優先順位
- 一人で完結する体験
- データの安全性
- 共有は後付けできる構造
この順番を崩すと、
「使われない共有機能」が最初にできてしまうと考えました。
現在の実装状況
現時点で実装している主な機能は以下です。
- 認証(ログイン)
- アルバムの CRUD
- 写真の CRUD
- ユーザー単位のデータ分離
まずは MVP として、
「思い出を自分のペースで残せる」体験を成立させています。
今後の拡張を見据えて
今後考えている拡張は、
- アルバム単位の共有
- 招待制のアクセス管理
- 思い出を振り返る UI / UX の改善
などです。
ただし、
機能を増やすこと自体が目的ではありません。
思い出を大切に扱える体験になっているかを、
これからも一番の判断基準にしていくつもりです。
おわりに
このアプリは、最新技術を試すための個人開発ではありません。
また、この設計が最適解だとも思っていません。
ただ、今の自分の目的と制約の中では、最も納得できる選択でした。
個人的な後悔と向き合いながら、
「こういうものがあったらよかった」
と思った体験を形にしている途中です。
同じような思いを持つエンジニアや、
個人開発をしている人の参考になれば嬉しいです。
Discussion