今回は RESTfulAPI とは何なのか、について深掘ります。
本記事は、2023年1月に投稿されたものをリライトしたものです。
情報が古い点があれば、SNSやコメントなどで指摘をお願いいたします。
更新日:2024年5月8日
この記事の対象者
- API という単語は分かる
- 普通の API と RESTful API の違いが分からない
- REST の4原則以外にも注意すべき点が気になる
そもそも API とは何なのか
要するに、アプリ同士が情報をやり取りするために必要なものです。
API とは、「Application Programming Interface」の略です。
つまり、アプリ同士を繋ぐ窓口のようなものです。
次の画像を見てください。
この図のように、API は Awesome App から送られたリクエストを操作して、他のアプリからの情報を取得する役割を果たします。
具体的には、データベースの値を書き換えたり、他のアプリのデータ処理を行ったりすることができます。
つまり、API はアプリ同士が情報を共有し、相互に連携するための窓口として機能します。
API の種類
最初に、REST API 以外の API についても理解しておくことが重要です。
これにより、後の REST に関する内容をより理解しやすくなるかもしれません。
以下の4つは、主な API の種類を分類したものです。
REST API はすべての API に共通していますので、学習しておくと役立ちます。
RESTful API とは
RESTful API は、REST の原則に則って構築された Web システムのインターフェースのことです。
ここで、REST と RESTful の違いについても触れておきましょう。
分かりやすいように、オライリー社が定義している基準で使い分けます。
1. 完璧な REST は REST API と呼び、そうではない場合は RESTful API と呼ぶ。
RESTful Webサービス – O’REILLY
2. REST 原則に従わないものは REST という言葉を使わず、HTTP API などと呼ぶべきである。
3. RESTful の -ful は「満たす」を意味するので、RESTful API は REST の原則を満たすべきだ。
これから記事を読んでいく上で、「これが REST 原則を満たしていない」と感じた方は、RESTful API を作成できていないことを意味します。
誤解を避けるためにも、HTTP API や Web API と呼んで開発するのが良いかもしれません。
REST の原則
RESTとは、「REpresentational State Transfer」の略で、Webサービスの設計モデルの1つです。HTTPのシステムアーキテクチャを効率的に活用するために設計されており、データの送受信をHTTPメソッドを使って行うモデルを指します。
RESTアーキテクチャを考えると、4つの原則が浮かび上がりますが、実際には、提唱された論文では原則という言葉は使われていません。
代わりに、提唱された考えを他者が解釈し、その結果が現在のRESTful APIの4つの原則となっているようです。
以下は、提唱者であるRoy Fieldingが書いた論文です。
全文は英語ですが、興味のある方はぜひご覧ください。
Stateless (状態不要)
Stateless とは、セッションやその他の状態管理を行わない、通信規約( HTTP プロトコル)のことです。
ユーザーから送られたリクエストを処理する際に、履歴やクッキーの操作などを行わないものを指します。
サーバーで不要な情報を持たないので、開発者としては実装が容易です。
ステートの管理は、その他の状態管理ライブラリなどを使用することで取り扱うことができます。
Uniform Interface (統一インターフェース)
統一インターフェースとは、リソース全体に適用できる「情報操作の命令体系」が定義され、共有されていることを指します。
インターフェースが統一されていればブラウザ・JavaScript コード・モバイルアプリケーションなど REST を利用するクライアントであれば同じ方法でサーバーが呼び出せます。
下記の画像のように、永続的なデータを扱うソフトウェアに要求される4つの基本機能を指します。
Addressability (アドレス可能性)
下記のアドレスを見てください。
・https://weathernews.jp/s/forecast/?area=TOKYO
これは東京都の天候を取得する API の URI ですが、一目見て分かるように、東京の天気を表すものです。 DX (開発者体験)を向上させるために、このようにわかりやすい工夫が重要です。
これだけでは分かりづらいと思いますので、イメージ画像を作成してみました。
以下の例のように、相互にアクセスしやすい思想のことを指します。
GOOD の方は、アドレスを指定して接続でき、かつ、接続されています。
接続されているリソース同士は相互にリンクされているため、RESTful サービスとなります。
BAD の方は、リソース同士が相互に接続されておらず、その間の関係を示すものがありません。
このような形になるのは、REST と RPC の両方を考慮したサービス、または Amazon S3 のようなストレージを管理するサービスの場合かもしれません。
API アドレスに動詞は好ましくない
API のリソースでは、動詞を使わない方が好ましいとされています。
例えば、アドレスに操作方法を含めるようなものは、例えば、get_profile や post_profile のようにするのは避けるべきです。
さらに、クエリパラメータを含めることでややこしくなるかもしれません。
と言われても分かりづらいと思いますので、実例を出しましょう。
GET http://impl.co.jp/achievement?listSort=desc&listOrder=1
動詞が含まれていることにお気付きでしょうか?
このように、クエリパラメータについても気を配る必要があります。
Connectability (接続性)
やりとりされる情報内部には、別の情報や(その情報の別の状態)へのリンクを含めることができます。
1つのリンクから別の情報にリンク(接続)することができて、RESTful なシステム同士なら円滑に情報連携を行うことができます。
下記に示した画像を見てください。
これは、ショッピングサイトの会員情報のリソースを例にとって、リソースの接続性について説明します。
このようにすることで、リンクを介することでリソース同士の結合は疎のまま、値を参照しやすくなります。
これでは不十分?
私も、以前は、上記の条件を守っていれば、RESTful な API を作っているという認識でした。
ですが、X(旧 Twitter) を見ているときに、このようなポストを見つけました。
自戒を含むけど,人々 REST API に囚われすぎる節あるよね.これ REST(ful) にするのむずくね?って思った時は AWS の API を思い出しているよ
— Siketyan (@s6n_jp) February 15, 2024
ここからは、このポストが何を課題に思っているのかについて話して行きます。
HTTP メソッドの使い分け
REST API では、HTTP メソッドを使い分けることが必要です。
情報操作の命令体系を明確にし、わかりやすくすることができます。
特に、POST メソッドは、新しいリソースを作成するために使用されます。
したがって、POST メソッドを使って情報の取得を行うことは、本来の役割から外れているため、好ましくありません。
ですが、POST メソッドで GET 処理をしなければならない場合とは、具体的にどのようなシチュエーションを指すのでしょうか?
パラメータを含んでいる場合
検索フォームを送信する時や、ページングしている時に、リクエストパラメータを含んでいる場合はPOST メソッドを使うことがあります。
リクエストパラメータとは、リクエストを行うときに、URL やリクエストボディに付加する値のことです。
サーバーに対してリクエストを行うときに、サーバーがリクエストをどのように処理するかを決めるためのものになります。
例えば、リクエストを送るときに、リクエストにおいて検索する文字列や、表示するページ番号や、表示するデータを並べる順番を指定することができます。
情報の取得時に、同時にデータの作成や更新を行う場合
データを作成や更新する場合は POST メソッドを使います。
POST メソッドは情報の取得を行うものであり、情報の取得や更新、削除の操作は行わないようにしましょう。
API のバージョン管理
API のバージョンを管理することも、RESTful な API を構築する上で重要です。
理由としては、API の変更によって既存のシステムに影響を与えることを防ぐことが挙げられます。
また、他のチームや組織が API を利用する場合にも、その API の変更を受け入れらやすいようにする予防策でもあります。
このように、API のバージョンを管理することで、API を使用する側のシステムやプログラムを変更せずに、API の変更を受け入れることができるようになります。
パフォーマンスを意識する
キャッシュを使う
REST API の呼び出しは、リソースを取得するためのコストがかかります。
キャッシュを有効にすると、エンドポイントのレスポンスがキャッシュされて呼び出しの数を減らすことが出来ます。
また、API へのリクエストを出してから実際にデータが送られてくるまでに生じる、通信の遅延時間を短くすることもできます。
キャッシングの構成は、主に2つに分かれています。
下記の画像を見てください。
キャッシュアサイドパターン
最も単純な実装のため、よく使われると思います。
具体的なミドルウェアとしては、Redis や Amazon API Gateway などが挙げられます。
デメリットとしては、最初のキャッシュが遅くなることや、アプリケーション側でキャッシュとデータベースを区別する必要があるという点があります。
しかし、Key Value Store に保存するだけなので、使用する上ではそこまで問題にならないと思われます。
ブローカーパターン
アプリ側がデータストアを意識する必要がないパターンです。
このパターンを使うためのサービスとしては、Amazon DynamoDB Accelerator が一例です。
先ほどの画像で言うと、Cache コンポーネントが Broker の役割を果たします。
Broker は、適切なサーバーを見つけてリクエストを転送し、結果をクライアントに送信します。
データを圧縮する
API Gateway コンソール、AWS CLI、または AWS SDK を使用して、API の圧縮を有効にできます。
API のペイロードの圧縮を有効にする – Amazon API Gateway
既存の API では、圧縮を有効にした後、API をデプロイして変更を有効にする必要がありま
リクエストで送信されるデータやレスポンスで返されるデータを圧縮することで、通信帯域を節約できます。
つまり、レスポンス時にヘッダー情報やその他のリソースを圧縮し、REST API で処理する前に展開することで、パフォーマンスを向上させることを意味します。
パラメータを最小限にする
リクエストパラメータを最小限にすることで、リクエストを軽くすることができます。
例えば、アプリケーションでユーザーの情報を取得する REST API を作成する場合、以下のようなパラメータを最小限にすることができます。
👍 GOOD パターン
GET /users/{user_id}
このように、必要な情報をすべて user_id
に詰め込んで、1つのパラメータで受け取ることで、リクエストのパラメータを最小限にすることができます。
👎 BAD パターン
GET /users?first_name=John&last_name=Doe
このように、複数のパラメータを使用して情報を取得すると、リクエストのパラメータが増えてしまいます。また、必要な情報が複数のパラメータに分かれているため、リクエストを理解するのが難しくなる可能性もあります。
非同期処理を検討する
長時間かかる処理は、非同期で行うことで、他の処理をブロックすることなく実行できるようになります。
具体的な例としては、以下のようなケースが考えられます。
- データベースへの接続が遅い場合
- ファイルの読み込みや保存が遅い場合
- ウェブサイトへのアクセスが遅い場合
ここでは、データベースへの接続が遅い場合を考えてみましょう。
アプリケーションでは、データベースから情報を取得する処理があるとします。
この場合、データベースへの接続が遅いと、その処理が完了するまで他の処理が止まることになります。
その結果、アプリケーション全体のパフォーマンスが低下する可能性があります。
データを分割する
大きなデータを一度に取得するのではなく、必要なデータだけを必要なタイミングで取得するようにすることで、転送量を減らすことができます。
具体的な例としては、以下のようなケースが考えられます。
- アプリケーションでは、投稿一覧を表示する機能があるとします。この場合、すべての投稿を一度に取得することもできますが、データが大量である場合は、複数のリクエストを使用してデータを分割して取得することができます。
以下のようなエンドポイントを作成することで、データを分割して取得する REST API を実装することができます。
GET /posts?offset=0&limit=10
GET /posts?offset=10&limit=10
GET /posts?offset=20&limit=10
このように、offset
パラメータでデータの開始位置を、limit
パラメータでデータを取得する数を指定することで、データを分割して取得することができます。
パフォーマンスを監視する
REST API のパフォーマンスを定期的にモニタリングして、問題を早期に発見したり、パフォーマンス向上の目安を得ることができます。
ログの収集
アプリケーションでは、API リクエストやレスポンスの情報をログとして収集することができます。
これらのログを分析することで、API のパフォーマンスを把握することができます。
これは、よく使用されるもので言うと、console.log などの JavaScript の標準的な実装に組み込まれている機能の一つのことを指します。
監視ツールを使用する
監視ツールとは、アプリケーションやサーバーのパフォーマンスを可視化するためのツールです。
これらのツールを使用することで、API のパフォーマンスをリアルタイムでモニタリングすることができます。
有名なものには、datadog などがあります。
そこまで厳密な要求がない場合は、開発者ツールで秒数を確認するだけでも十分です。
ベンチマークテストを行う
ベンチマークテストとは、アプリケーションやサーバーが持つパフォーマンスを測定するためのテストです。このテストを行うことで、API のパフォーマンスを詳細に分析することができます。
ログの収集やベンチマークテストを行うことで、REST API のパフォーマンスを監視することができます。
サブリソースの設計
サブリソースとは、リソースの下に存在するリソースのことを指します。
例えば、「http://example.com/users/123」という URL で表されるリソースがあるとします。
このリソースの下には
・http://example.com/users/123/orders
・http://example.com/users/123/comments
などがサブリソースとして存在することが考えられます
サブリソースを使うことで、より細かい情報を扱うことができるようになります。
また、親リソースを参照しないで単独でも意味を持つことができるため、より自己完結型のリソースとして扱うことができます。
ステータスコードの使い分け
HTTP ステータスコードは、Web サーバからのレスポンスの状態を表すために使われます。
標準的なステータスコードは3桁の数字で表され、その数字が意味する状態を示しています。
一般的に使われるステータスコードには、以下のようなものがあります。
100番台 情報のメタデータが返却される
・100 Continue | リクエストが継続されることを示す。
・101 Switching Protocols | サーバーがリクエストされたプロトコルを切り替える。
200番台 リクエストが正常に処理され、レスポンスが返される
・200 OK | リクエストが成功し、情報が返される
・201 Created | 新しいリソースが作成され、その URL が Location ヘッダに含まれる
300番台 リクエストを処理するために追加アクションが必要
・301 Moved Permanently | リクエストされたリソースの URL が永久的に変更される
・302 Found | リクエストされたリソースの URL が一時的に変更される
400番台 クライアントからのリクエストが正しくない
・400 Bad Request | リクエストが不正である
・401 Unauthorized | リクエストを処理するために認証が必要である
・403 Forbidden | リクエストは許可されているが、リソースを取得する権限がない
・404 Not Found | リクエストされたリソースが存在しない
500番台 サーバ側で問題が発生し、リクエストを処理できない
・500 Internal Server Error | サーバ側で予期せぬエラーが発生した
これらのステータスコードを適切に使い分けることで、クライアントからのリクエストを正しく処理することで、快適な開発ライフを送ることが出来ます。
アンダースコアは好ましくない
REST API では、記号を使ったり URL を記述するときには、ハイフンを使うことが推奨されます。
これは、ハイフンは URL のエンコーディングによって改変されず、アンダースコアは改変されることがあるためです。
例として、アンダースコアを使用した URL をエンコードした場合にどうなるのか見てみます。
以下のURLをご覧ください。
・https://impl.com/api/items/item_id_1
これをエンコードすると、次のようになります。
・https://impl.com/api/items/item%5Fid%5F1
このように、アンダースコアはURLエンコーディングによって変更されることがあるため、REST API ではハイフンを使うことが推奨されます。
冪等(べきとう)性の考慮
冪等性を持たない API を使用すると、アプリケーションやサービスが不安定になることがあります。
例えば、同じリクエストを何度も送っても、サーバーがそれを1回しか処理しないようなAPIを使うと、アプリは複数回リクエストを送っても期待した結果が得られないことがあります。これはユーザーにとって不便であり、サービスの信頼性を損なう原因になります。
冪等性を持たせることで、サーバー側でリクエストを処理する回数が増えても、アプリケーションやサービスが正常に動作するようにすることができます。
リクエストを送信する度にインクリメントする、といった処理を行いたい場合は考慮しなくても良いです。
参考
Architectural Styles and the Design of Network-based Software Architectures
その他の記事
【カテゴリ別 】利用率ランキングから見る “今、本当に使われている” フロント技術トレンド【2023】