Sakiのプログラミング学習ブログ

プログラミングについて学んだことや、学習の振返りを書いています。

TwitterのURL設計を通して学んだこと

フィヨルドブートキャンプの「TwitterのURLを設計する」という課題を合格したので、URL設計について学んだことをまとめた。

URL設計とは

1. リソースにどんな名前をつけるか(どんなURLにするのか)
2. 決めたURLに対して、どのHTTPメソッドを使うか

を決めること。

Method Path Description
GET /foo fooの一覧を表示。
POST /foo fooを受け取って追加する。
DELETE /foo/123 fooのidを受け取って削除する。
GET /bar barの一覧を表示。

URL設計について書く前に、リソース,URL,HTTPメソッドについて説明する。

URLとは、リソースに名前を付けたもの

リソースとは

  • Web上に存在する、名前をもったありとあらゆる情報
  • URLと聞くと、Webページのアドレスを思い浮かべがちだが、他にも色々ある。
    例えば、Web上にある、

    • 写真
    • 文献・論文
    • 自分が登録したブックマーク
      なども全てリソースである。
  • リソースは、人の名前などと違って必ず一意の名前(その情報だけを指す名前)でなければならない。

URLとは

  • リソースに名前をつけたもの。
  • URLの基本的な仕様:uriスキーム/ホスト名/パス。もっと複雑な仕様もある。
  • TwitterのURL設計の課題では、このパスの部分を設計した。
  • ホスト名が一意であること & URLがそのWebサービスの中で一意になるように設計することで、リソースは世界で一意になっている。

HTTPメソッドとは

  • WebブラウザからWebサーバに対してのお願い。
  • 正式名称:HTTPリクエストメソッド

リクエストのどこに当たるのか

(HTTP入門 - とほほのWWW入門 より引用)

  • リクエストは以下の3つの部品から構成されている。
    1. リクエストライン
    2. リクエストヘッダ
    3. リクエストメッセージボディ

  • この2. リクエストヘッダの中にHTTPメソッドが含まれている。
    メソッド パス名 HTTP/バージョン

HTTPメソッド一覧

  • お願いには色んな種類がある。
メソッド 何をするか
GET リソースの取得
POST 子リソースの作成、リソースへのデータ追加、その他処理
PUT リソースの全部更新、リソースの作成
PATCH リソースの部分更新
DELETE リソースの削除
HEAD リソースのヘッダ (メタデータ)の取得
OPTIONS リソースがサポートしているメソッドの取得
TRACE プロキシ動作の確認
CONNECT プロキシ動作のトンネル接続への変更

※ LINK / UNLINK は、HTTP/1.1 ~廃止された。

POSTとPUTの違いは、URIの決定権

  • POST
    • サーバー側が決める
  • PUT
    • クライアント側が決める。
    • リソース名をクライアント側が指定して作成or更新をかけるメソッド。
    • 新規作成も更新も同じ書き方。
      例えば、PUT /articles/3421は新規作成かもしれないし、更新かもしれない。
      →リクエストされた時に、既存のリソースだったら更新し、新しいURLだったら新規作成する動作を行う。
    • 例:Wikipediascrapboxは、ユーザーが付けた記事のタイトルがそのままURLになっている。

(鬼滅の刃 - Wikipediaより引用)

  • Twitterの設計では、クライアント側がURLを決める必要性を感じなかったため、PUTを使った。

PUTは全部更新、PATCHは部分更新

PATCHメソッドは『Webを支える技術』には載っていなかったので、PUTとの違いを調べた。

  • PUTメソッド

    • べき等である
    • リソースの全部を更新
      ブログの記事に例えると、記事の内容を全部変えるのがPUT。
  • PATCHメソッド

    • べき等でない
    • リソースの一部分を更新
      ブログの記事に例えると、記事の台頭だけを変えるのがPATCH。
  • リソースの一部更新をする場合には、そのリソース (URL)へPATCHリクエストを投げるのが、最も自然な設計。
  • PATCHはべき等が必ずしも保証されていないメソッドのため、PUTとDELETEを組み合わせた設計のほうが、シンプルでねき等性のある設計になることもある。

  • Twitterの設計では、リソースを部分的に更新するような機能の設計はしなかったので、PATCHメソッドは使わなかった。

URL設計で気をつけること

  • パスのネストは最小限に抑える
  • 名詞を使う
  • ホスト名がこの世に一意であることと、URLが一意であることで、リソースは世界で一意となる。なので、URLを設計する時は、一意を示す設計をしなくてはいけない。
  • メソッドとパスの掛け合わせが重複しないようにする

メソッドとパスの掛け合わせが重複しないようにする

最初、以下のように提出した(一部抜粋)

Method Path Description
GET /user_id ユーザーを表示する
GET /tweet_id ツイートを表示する

レビューで以下のようにご指摘をいただいた。

  • このuser_id, tweet_idには、シンプルに考えると数字が入ってくる。
  • ユーザーのプロフィール画面を表示するURLと特定のツイートを表示するURLは別物だが、数字を入れてみると、URLとメソッドの掛け合わせが重複してしまうことが分かる。
Method Path Description 数字入り想定Path
GET /user_id ユーザーを表示する /128
GET /tweet_id ツイートを表示する /128
  • この設計は一見、/user_id/tweet_idで区別できているように見えるが、リクエストを処理するサーバにとってはまったく同じものに見えて区別ができない。
  • この問題を解決するために、サーバーがどのテーブル(リソース)を参照すれば良いか把握できるようにしてあげる必要がある。

このため、最終的に以下の設計にした。

Method Path Description
GET /users/:user_id ユーザーを表示する
GET /tweets/:tweet_id 特定のツイートを表示する

これなら、idの部分が重複しても、

  • /users/123
  • /tweets/123

となり、区別できる。

感想

  • 最初、Twitterの何がリソースに当たるか分からず、混乱した。
  • ツイートの新規作成画面を取得するリクエストと、ツイートを行うリクエストは、ブートキャンプの日報作成時のURLを参考にさせていただいた。
  • URL設計は、Sinatraのメモアプリ作成課題でも行うので、大事。
  • 設計はコードを書く時と同じで正解が一つでないので、
    課題修正時に、「なぜその設計にしようと思ったか?」を述べるようにしたら、メンターさんから、以下のように仰っていただけたのが嬉しかった🥰
    • 理由を述べることができるというのはとても大事な能力
    • ぜひ今後も「どうしてこういう設計/実装になったの?」と聞かれた時に答えられる姿勢で進めてほしい

参考書籍・記事