ここから設計編です。まず技術選定から。
前提として、作れる期間は 1 か月半、作るのは1 人でした。この制約が、ほぼすべての判断を決めています。
判断の軸を先に決めた
候補を比べる前に、何を優先するかを決めました。
| 優先 | 軸 | 理由 |
|---|---|---|
| 1 | 1 か月半で作り切れるか | 期限が動かない |
| 2 | 学習コストが低いか | 授業で触ったものがあれば、それが一番速い |
| 3 | 表示が速いか | 要求定義書に「表示 3 秒以内」と書いた |
| 4 | 現場で主流か | 就職を考えると、使われているものを触りたい |
| 5 | 無料枠で収まるか | 学生なので費用をかけられない |
以降の表は、この 5 つで採点した結果です。迷ったら上の軸を優先しました。
やったこと:候補を挙げて比べた
| 層 | 候補 | 結果 |
|---|---|---|
| 言語 | TypeScript / PHP | TypeScript |
| 画面 | Next.js / Laravel / React(素のまま) / TanStack | Next.js |
| DB | Supabase / Firebase | Supabase |
| ホスティング | Vercel / Netlify / Cloudflare / 自前サーバー | Vercel |
| 地図 | Google Maps / Mapbox / OpenStreetMap | Google Maps |
判断:Next.js と Laravel を比べる
Next.js
| 良い点 | 画面とサーバー(API)を同じ言語・同じプロジェクトで書ける。 行き来が少なく、型も共有できる |
| サーバー側で先に HTML を作って返せるので表示が速い。静的に作っておくこともできる | |
| Vercel にそのまま載る。 サーバーの用意・運用が要らない | |
| 現場で主流。求人も多い | |
| 悪い点 | サーバーレス前提の制約がある(実行時間の上限・常時接続が苦手・重い処理に向かない) |
| バックエンドの道具が最小限。 ORM・認証・バリデーションはほぼ自分で組むか、外部に任せる | |
| 作り方の流儀が変わりやすい(App Router など) |
Laravel
| 良い点 | バックエンドの道具が最初から揃っている(ORM・マイグレーション・認証・バリデーション・キュー・定期実行) |
| MVC の型があるので、設計の迷いが少ない | |
| 長時間かかる処理や定期実行が素直に書ける | |
| 授業で習っていた | |
| 悪い点 | 言語が 2 つに分かれる。 画面は JavaScript、サーバーは PHP |
| 地図や写真を触るような画面主体のアプリには、別途フロントの構成が必要 | |
| サーバーの用意と運用が必要。 push しただけでは公開されない | |
| 画面とサーバーで型を共有できない |
総合して Next.js にした理由
- このアプリは画面が主役。 地図・写真・タイムラインが中心で、サーバーは「データを渡す」側
- バックエンドの道具は Supabase が埋める。 ORM・認証・ファイル保存を任せられるので、Laravel の一番の強みが相殺された
- 軸 3(表示が速いか)に直接効く。 サーバー側で先に描いて返せる
言語を 2 つ行き来する構成は、それだけで時間を食います(軸 1・2)。
素の React を選ばなかった理由
React だけでも作れます。ただし画面しか付いてきません。ルーティング、サーバー側の描画、API、画像の最適化、ビルドの設定を、自分で選んで組み合わせることになります。
決める量が増えるほど、1 か月半は削られます。レールに乗って迷いを減らすほうを選びました。
TanStack を選ばなかった理由
新しい選択肢として候補に入れましたが、情報が少ないことがそのまま危険でした。詰まったときに調べて解決できないと止まります。
「情報が少ないなら、自分が記事を書く側になればいい」とも考えましたが、作るのと書くのを同時にやる余裕は無いと判断しました。
(結果として、こうして今は記事を書いています。順番が逆になっただけでした。)
判断:Supabase と Firebase を比べる
Supabase
| 良い点 | SQL(PostgreSQL)が使える。 投稿・スポット・アルバム・しおり・メンバーのように関係が多いデータを素直に書ける |
| **RLS(行ごとの権限)**が使える。「自分の非公開投稿は自分だけ」をデータ側で書ける | |
| テーブルを作るとAPI が自動でできる。認証とファイル保存も同じサービス | |
| SQL の知識が実務にそのまま転用できる | |
| 悪い点 | 無料枠だと一定期間使わないと止まる |
| 接続数の上限がある(サーバーレスから繋ぐときに注意が要る) | |
| リアルタイム(同時編集のような機能)は Firebase のほうが得意 |
Firebase
| 良い点 | リアルタイム同期が強い。通知・分析・クラッシュ検知が最初からそろっている |
| 実績が多く、情報も多い | |
| 悪い点 | NoSQL なので JOIN が無い。 「このアルバムのメンバーが投稿した写真」のような関係をまたぐ取得が面倒 |
| クエリに制約がある。集計も苦手 | |
| 読み取りの回数で課金されるので、料金が読みにくい | |
| SQL の経験にならない |
このアプリは「関係が多いデータ」だった
投稿はスポットに属し、アルバムに入り、メンバーが共有し、しおりとつながります。ここで JOIN が無いのは厳しく、Supabase を選んだ理由はほぼこれです。
判断:ホスティングは Vercel
| 候補 | |
|---|---|
| Vercel | 採用。 Next.js を作っている会社のサービスで、設定なしでそのまま動く。push すると公開され、PR ごとに確認用の URL もできる。無料枠で収まる |
| Netlify・Cloudflare | 却下。 動くが、Next.js の新しい機能への追随が一歩遅れる |
| 自前のサーバー(VPS) | 却下。 Linux の設定・証明書・監視を自分で持つことになる。1 人・1 か月半では無理 |
**代わりに受け入れたのが「サーバーレスの制約」**です。重い処理や常時接続ができません。次回はその話を書きます。
判断:地図は Google Maps
| 候補 | |
|---|---|
| Google Maps | 採用。 日本の店の情報が圧倒的に多い。スポット候補の検索と、住所→座標の変換が同じ系列で揃う |
| Mapbox | 却下。 地図の見た目は自由に作れるが、日本の店の在庫が弱い |
| OpenStreetMap(Leaflet) | 却下。 無料だが、店の検索を別サービスで用意することになる |
このアプリは「実際に行った店」を扱うので、店の在庫がそのまま品質になります。 「近所のたこ焼き屋を検索して出てくるか」が決定的でした。
ただし Google Maps は使った分だけ課金されます。このアプリで費用が発生するのはここだけなので、無料枠に収める工夫をしました(後の回で書きます)。
そのほかに決めたこと
PWA にして、ネイティブアプリを作らなかった
iOS と Android の両方を 1 人で作る時間はなく、ストアの審査も待てません。ブラウザで動く 1 つのものを作り、スマホでもパソコンでも同じ画面を出すことにしました。
ORM を使わなかった
Prisma のような道具は入れず、Supabase のクライアントで直接書いています。テーブルが自動で API になるので、間に ORM を挟む利点が小さいと判断しました。
代わりにSQL と RLS を自分で書くことになり、結果としてこちらのほうが勉強になりました。
技術選定のポイント(次に選ぶとき)
今回やってみて、順番にやれば迷わないと分かったことを並べます。
| # | ポイント |
|---|---|
| 1 | 軸を先に決めて、順位を付ける。 候補を見てから考えると、見た目の新しさに引っ張られる |
| 2 | 1 つずつでなく「組み合わせ」で見る。 Supabase を取ると Laravel の強みが消えるように、ある選択が別の選択の価値を打ち消す |
| 3 | 「学習コストが低い」を軸に入れてよい。 期限がある個人開発では、これが最優先になることもある |
| 4 | データの形で DB を決める。 関係が多いなら SQL、一覧とリアルタイムが中心なら NoSQL |
| 5 | 情報量を軸にする。 詰まったときに調べられるかは、期限のある開発では機能の数より重要 |
| 6 | 課金が発生するものを数える。 少ないほど運用が楽。今回は地図だけに絞れた |
| 7 | 「何を捨てたか」を自覚する。 Vercel を取る=サーバーレスの制約を受け入れる。捨てたものを書いておくと、後で困ったときに「想定どおり」と分かる |
| 8 | 却下した候補と理由を文書に残す。 これを怠ると、次の項目のようになる |
| 9 | 替えにくいものだけ慎重に選ぶ。 DB・ホスティング・認証は後から替えにくい。見た目やテストの道具は走りながら決めてよい |
気をつけたこと:とにかく期限に間に合わせる
技術選定でいちばん気をつけたのは、提出日に間に合わせることでした。
機能は削れますが、日付は削れません。だから「いちばん良い技術」ではなく「自分が 1 か月半で動かせる技術」を選びました。
守ったことは 3 つです。
1. 新しく覚えるものを増やしすぎない。 授業で触っていた Next.js を軸にして、初めて使うものをできるだけ少なくしました。知らないものを同時に 2 つ以上入れると、詰まったときにどちらが原因か分かりません。
2. 比べるのに時間をかけすぎない。 候補を調べるのは楽しいので、いくらでも時間を使えてしまいます。軸を先に決めておいたので、軸で決まるものは即決しました。
3. 「あとで替えられるか」で慎重さを変える。
| 替えにくい | 替えやすい |
|---|---|
| DB(データの形が変わる=全部直し) | 画面の見た目 |
| ホスティング | テストの道具 |
| 認証の方法(アカウントの結びつけが残る) | 入力検証の書き方 |
替えにくいものだけ時間をかけて、替えやすいものは走りながら決めました。 実際、入力検証の仕組みは提出後に入れ替えています(改善編で書きます)。
それでも全部は終わらなかった
正直に書くと、提出日に全機能は終わっていません。開発順序の文書には、早い段階でこう書いていました。
提出日に対して全 Phase は完了しない見込みのため、受入条件のうち外せないものを別途選定すること
「間に合わせる」は「全部作る」ではありません。 何を落とすかを先に決めておくことでした。
決めた決まり
- 技術を選ぶ前に、軸を順位付きで書く
- 技術を選んだら、却下した候補と理由も同じ文書に残す
- 「捨てた制約」も一緒に書く(あとで困ったときに想定内と分かる)
- 課金が発生するものは最小限にする
次回
次は、この構成から自動的に決まってしまったことです。Vercel のサーバーレスで動かすために、諦めた方法が 3 つありました。