ブログリファクタリングプロジェクト-1- (Feat. RESTful API)
2025年03月12日
そろそろ忙しかったスケジュールも一段落してきたので、ずっと後回しにしていたフロントエンドのNext.js導入を始めようと思う。
ただ、フロントエンドについては、ブートキャンプの中で1週間くらい軽く触れたHTML + CSS + JavaScript程度しか知らない。実際に今このブログもその3つの組み合わせでできているし、MusicLabプロジェクトでフロントエンドと連携を取る前に、自分でshadcnを使ってみようとしてAIと一緒に涙ぐましい悪戦苦闘を繰り広げたことがあるけど、結局失敗して、協力してくれる人を探すことを悩んだりもした。
でも今はブートキャンプも終わったし、当時一緒に作業していたフロントエンドの方も就職活動で忙しそうなので、手伝ってとは言い出せる雰囲気じゃない。そして今はあの頃とは違って、ClaudeのSonnet 3.7やOpenAIのo3-mini-highなど、コーディング特化型のAIがかなり進化してきたので、今回は一人で挑戦してみるつもりだ。いつまでもあの「過去の遺産」みたいな構成に頼るわけにはいかないし。
導入のために色々と調べている中で気づいたことがある。現時点でNext.jsを導入するには、今のFastAPIのエンドポイントをRESTfulに修正しなきゃいけないという事実だ。
その理由は大きく2つある。
-
データ通信の標準化
- Next.jsのfetch()やgetServerSidePropsが期待しているGET/POST/PUT/DELETEのメソッドとエンドポイント構造に合わせるため。 -
リソース中心のアーキテクチャ
-/users/{id}のような階層的URL構造がNext.jsの動的ルーティング(pages/users/[id].js)と自然に連動する
- バージョン管理にも便利(/api/v1/のようなプレフィックスで将来的な変更にも後方互換性を持たせられる)
この事実を知って、自分のAPIのエンドポイントやHTTPメソッド、実際の構造を見てみたら、もうひどすぎて笑えなかった。 全部書くと長すぎるので、特に問題が目立つところだけ挙げてみる。
-
RESTful原則の無視
- リソース取得にGETを使う時もあればPOSTを使う時もある
- ログアウトにGETを使っている -
一貫性のないURL構造とアクション中心のURL
- アクションが先に出る構造(例:/edit/{post_id})
- リソースが先に出る構造(例:/post/{post_id}/toggle-publish)
- RESTful APIはリソース中心であるべきなのに、アクション中心なだけでなく、パターンもバラバラ -
重複するエンドポイント
- 同一URLに異なるメソッドを使う(例:/writeはGETでUIをレンダリングし、POSTで投稿を登録)
「いくつか」と言いつつ、改めて見るとマジでカオスだった。だからまずは概念だけはなんとなく知っていたRESTful APIの設計について、自分なりに調べたことをまとめてみようと思う。
RESTful APIとは?
REST(Representational State Transfer)アーキテクチャスタイルの設計原則に従ったAPIのこと。
RESTful APIの特徴
- リソース中心の構造:URIでリソースを明確に表現
- HTTPメソッドの活用:GET, POST, PUT, DELETEなどでCRUDを実行
- ステートレス:すべてのリクエストは独立していて、サーバーは状態を保持しない
- キャッシュ可能性:レスポンスをキャッシュしてパフォーマンス向上
- クライアント・サーバー構造:役割が明確に分離されている
- 階層構造:セキュリティやロードバランシングのために多層化可能
- インターフェースの一貫性:標準化された方法で情報をやりとりし、システム統合がしやすくなる
実はこの中で自分が守っていたものは一つもなかった。 上で言ったように、リソース中心ではなくアクション中心のエンドポイントを設計していたし、その上一貫性すらなかった。HTMLメソッドもPUTやDELETEなんてほぼ使っていなかった。
ブートキャンプ中、メンターが他の受講生のWebアプリを見て、「今の自分みたいにedit/{id}なんて書くなよ」って言ってたのを横で聞いたことがあるけど、当時は「何の話?」と思ってた。でも今見てみると、あれは完全に経験から滲み出た言葉だったんだなと痛感した。
じゃあ、どうやって設計すべき?
RESTful APIの設計で一番大事なのは、URIはリソースを表現し、行動はHTTPメソッドで表現すること。
これをちゃんと理解すれば、APIはスッキリした構成になる。
1. URIは情報のリソースを表現する
❌ 悪い例:
/getUsers, /createProduct, /updatePost, /deleteComment
⭕ 良い例:
/users, /products, /posts, /comments
- コレクション(複数形)と単体リソース(単数形)を区別する
2. HTTPメソッドで行動を表現する
❌ 悪い例:
GET /posts/show/1
POST /posts/insert/2
⭕ 良い例:
GET /posts/1
POST /posts
3. リソース間の階層構造を反映する
❌ 悪い例:
GET /comments?postId=1
⭕ 良い例:
GET /posts/1/comments
4. URIの末尾にスラッシュを付けない
❌ http://api.example.com/users/
⭕ http://api.example.com/users
5. URIはすべて小文字で書く
❌ /Users/Kim
⭕ /users/kim
6. 可読性のためにハイフン(-)を使う
❌ /products/electronics/computer_accessories
⭕ /products/electronics/computer-accessories
7. クエリパラメータでフィルタ・ソート・ページネーション
❌ 悪い例: /users?q=Kim&f=25&o=asc&l=2
⭕ 良い例: /users?name=Kim&age=25&sort=asc&page=2
8. 特定の動作が必要な場合は動詞を使ってもOK
❌ /users/1/status
⭕ /users/1/activate
❌ /products/123/delivery
⭕ /products/123/send
結論
こんな風に特徴と設計方針に沿って試しに設計してみたけど、さっき「おかしい設計」として挙げた /writeのGET/POST混在のケースは、RESTfulにするなら保存用のAPIだけ /postsにして、UIレンダリング用のGETは別で /writeに分けるのが筋。だけど、そうすると逆に構造が汚くなりそうな気もして、どこまで厳密にRESTfulのルールを守るべきか、それとも大枠だけ守って柔軟に対応すべきか、まだ迷ってる。
だからまずはFastAPIのエンドポイントや構成のリファクタリングは一旦後回しにして、Next.jsをビルドして今の構造と連携できるか確認してから、後で改めて手をつけることにしようと思う。
カカオ
グーグル
ネイバー