バックエンド未経験インフラエンジニアが、個人開発で AWS 上にバックエンドを作ってみて学んだこと①
(インフラエンジニアが個人開発しています→https://kondate-loop.com/)
私はこれまで、AWS を使ったインフラ寄りの仕事にはある程度触れてきました。
ただ、「自分でアプリケーションのバックエンドをゼロから設計して作る」という経験は、正直ほとんどありませんでした。
今回、個人開発しているプロダクトでその必要が出てきて、AWS 上にバックエンドを作るところまでやってみました。
この記事は、
- バックエンド未経験のインフラエンジニアが
- 個人開発の中で
- 設計と実装を少しずつ往復しながら
- AWS 上で動くバックエンドを作るまでに学んだこと
をまとめたものです。(長くなったので、①設計②実装③感想の3つに分割します!!)
完成されたベストプラクティスの話というより、どこを先に決めると進めやすかったか、どこは実装しながら固めるべきだったか、という学びの記録に近いです。(多分全然ベストプラクティスじゃない気がする・・・。完全にバイブコーディングの延長です。
先に作ったのはコードではなく、前提だった
今回のバックエンド実装で、最初にやったのは API を書くことでも、Lambda を作ることでもありませんでした。
まずやったのは、MVP として何を扱うのか、その前提をかなり丁寧に固めることでした。
たとえばこの段階で、ざっくり次のような方針を先に決めていました。
- まずは MVP に絞る(あれもこれもと実装していくと実装が汚くなりそうという予感がありました)
- Web を先に成立させる
- データの正本はサーバー側に置く
- オフラインは初期スコープに入れない
- 主要導線を先に固定する
これを先に決めておくと、設計がかなり楽になります。
逆にここが曖昧だと、認証、保存方式、同期、UI の期待値が全部ぶれます。
バックエンド未経験だと、つい「テーブルどう切ろう」「APIどう書こう」に意識が向きがちでした。
でも実際には、その前にこのバックエンドは何の責務を持つのかを決めないと、後からかなり崩れやすいと感じました。
少し話はずれますが、私は、システムは手段に過ぎないという考えを常に持っています。つまりバックエンドを作るが目的になることはなくて、何かをするためにこういうバックエンドという手段が必要だねという考えです。結果作るのだから、ニュアンスの違いだろと思う方もいるかもしれませんが、この思考でいると、システム開発が迷走しにくいと思います。
また個人開発だと、とりあえず動くものを作りたくなります。
ただ、最初の勢いで作ったものほど、後から直すコストが高くなることも多いです。(勢いで作って修正しまくったせいで、一週間分のClaudeCodeの使用量を週頭に消費した友人がいましたが、その友人も勢いで作るのをやめてからそういうことはなくなったそうです)
今回そこを先に整理したのは、かなり良かったと思っています。
API 設計を先に揃えると、実装中の迷いが減った
実装前の設計では、API 契約もある程度先に詰めました。
たとえば、
- パスのベースは
/v1 - ID は ULID 前提
- エラーフォーマットは共通化
- 一覧系は cursor pagination を前提にする
-
savedCountを人気指標として扱う
といったルールです。
このあたりを実装前に揃えておくと、API を 1 本ずつ書くたびに毎回設計思想を考え直さなくて済みます。
バックエンドを初めて触ると、最初は「まず 1 本動かしたい」という気持ちがすごく強いです。
でも実際に必要なのは、1 本だけ動く API よりも、同じルールで増やせる API 群でした。
共通化という考えは今後のアジャイル開発の世界では重要になってくるのではないでしょうか?アジャイル開発では、どうしても一回カオスな状況がうまれがちで、開発運用を回していく中でカオスを統治していく必要に迫られると思うのですが、ある程度共通性を持たせておくと後の整理も楽だと私は思います。塩梅が難しいとは思いますが・・・。(運用改善系のエンジニアだからそう思うのでしょうか(笑))
今回も、recipe、set、plan、shopping、fridge と広げていく中で、先に契約を揃えておいた恩恵をかなり感じました。
ドメイン設計は「正しさ」より「使い方」から考えた
今回の設計で面白かったのは、いわゆる厳密な分類や綺麗な正規化よりも、プロダクトとしてどう使われるかを優先したところでした。
たとえばカテゴリ設計です。
最初は「カテゴリを厳密に分類するもの」として考えがちだったのですが、最終的にはもっと柔らかく、タグ表示設定に近いものとして扱う方が自然でした。
また、archive も独立した機能として強く持つより、
「作った」という状態遷移の結果として自然に生まれるものと捉えた方が設計しやすくなりました。
さらに、外部共有についても、
認証必須の閉じた設計にするより、認証不要で見せられる代わりに出典は必須とした方が、このプロダクトには合っていました。
このあたりは、バックエンド実装というより、プロダクトの意味をどうデータモデルに落とすかの話だったと思います。
個人開発では、技術的に正しい設計を目指しすぎると、使い方から離れてしまうことがあります。
※フロントエンド先行かバックエンド先行かの話かもしれません。自分に詳しいバックエンド知識がない+フロントエンドが完成していたという状況だったので、こういうフロントエンド先行型の設計になっています。
DB 設計は ER 図起点ではなく、アクセスパターン起点で考えた
今回かなり学びになったのが、DynamoDB の設計です。
最初は、RDB に慣れた発想で「ER 図をきれいに作りたい」と思っていました。
ただ、実際に進める中で重要だったのはそこではなく、どんな取得・更新をしたいのかを先に並べることでした。
つまり、
- ユーザー情報をどう取るか
- ユーザーのレシピ一覧をどう取るか
- セット一覧をどう取るか
- current / next の献立をどう持つか
- 買い物リストや冷蔵庫をどう更新するか
- 公開 catalog をどう見せるか
といったアクセスパターンを先に列挙してから、PK / SK / GSI に落としていく形です。
この順番に変えてから、一気に設計が進みました。
Single Table Design も、最初はかなり身構えていました。汚い設計になるのではないか…と。
でも実際には「1 テーブルに無理やり何でも入れる」ではなく、アクセスパターンに意味を持たせてキーを設計するものだと理解すると、だいぶ見通しが良くなりました。←正直Codexが作ったものを見たときに、キー設計の意味をようやく理解できたので、設計の時は、まあなんかそうなんだくらいでしたね。出来上がりを見て感動しました。
個人的には、ここが今回いちばん「インフラの知識だけでは埋まらない部分」でした。
でも逆に言うと、ここを越えると DynamoDB 設計がかなり面白く見えてきました。
今回はここまでです。次の実装編もよかったらご覧ください。
またAWSで個人開発を行っている方からのコメントもお待ちしています!