📸

個人的体験から始めた、思い出共有フォトアルバムアプリの技術設計

に公開

はじめに

この記事は、個人的な体験をきっかけに作り始めた
「思い出を大切な人と共有するフォトアルバムアプリ」 について、

  • なぜこの技術構成にしたのか
  • なぜ最初から共有機能を作らなかったのか
  • 個人開発として何を優先したのか

といった 設計・技術選定の観点 をまとめたものです。

背景や思想については note に別途まとめているため、
ここでは エンジニア向けに技術面を中心 に書いていきます。

※ 本記事は、以下のnote記事で書いた内容を前提に、
技術設計・実装判断にフォーカスしています。
(背景や思想についてはnote側をご覧ください)

https://note.com/npower_creative/n/n50d6aaa067f5


このアプリの前提条件(技術要件)

最初に、このアプリを作る上での前提条件を整理しました。

  • 不特定多数向けの 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 との相性が良い

個人開発では、

インフラを触っている時間 = ユーザー体験が良くなる時間

とは限らないため、
フロントエンドに集中できる環境を優先しました。


なぜ最初から共有機能を作らなかったのか(設計判断)

技術的には、
最初から「家族共有」機能を作ることも可能でした。

ただ、あえて次の順番にしています。

  1. 一人で安心して使える
  2. 思い出を整理できる
  3. 共有はその延長線上

理由は、

  • 共有は設計が一気に複雑になる
  • 本当に必要な共有の形は、使ってみないと分からない
  • まずは「個人の体験」を完成させたかった

からです。

これは技術的制約ではなく、
プロダクト設計としての判断です。

設計上の優先順位

  1. 一人で完結する体験
  2. データの安全性
  3. 共有は後付けできる構造

この順番を崩すと、
「使われない共有機能」が最初にできてしまうと考えました。


現在の実装状況

現時点で実装している主な機能は以下です。

  • 認証(ログイン)
  • アルバムの CRUD
  • 写真の CRUD
  • ユーザー単位のデータ分離

まずは MVP として、
「思い出を自分のペースで残せる」体験を成立させています。


今後の拡張を見据えて

今後考えている拡張は、

  • アルバム単位の共有
  • 招待制のアクセス管理
  • 思い出を振り返る UI / UX の改善

などです。

ただし、
機能を増やすこと自体が目的ではありません。

思い出を大切に扱える体験になっているかを、
これからも一番の判断基準にしていくつもりです。


おわりに

このアプリは、最新技術を試すための個人開発ではありません。
また、この設計が最適解だとも思っていません。
ただ、今の自分の目的と制約の中では、最も納得できる選択でした。

個人的な後悔と向き合いながら、
「こういうものがあったらよかった」
と思った体験を形にしている途中です。

同じような思いを持つエンジニアや、
個人開発をしている人の参考になれば嬉しいです。

Discussion