REST APIとは

Representational State Transferの略であるREST、またはRESTful APIは、既存のプロトコルを利用するように設計されています。RESTはほぼすべてのプロトコル上で使用できますが、Web APIで使用される場合には、通常はHTTPを利用します。つまり、開発者はREST APIの設計を利用するために、ライブラリや追加のソフトウェアをインストールする必要はないということです。REST APIの設計は、ロイ・フィールディング博士の2000年の博士論文で提唱されました。特筆すべきは、その驚くほど柔軟なレイヤーです。データがメソッドやリソースに関連付けられないため、RESTは複数のタイプの呼び出しを処理し、さまざまなデータ形式を返すだけでなく、ハイパーメディアを正しく実装して構造的な変更を行うこともできます。

自社にニーズを満たしつつ、非常に多様な顧客ニーズを満たすAPIを構築できるのは、REST APIに備わっているこのような自由度と柔軟性のおかげなのです。SOAPと違い、RESTはXMLに制約されず、クライアントの要求に応じてXML、JSON、YAMLをはじめとするさまざまな形式で返すことができます。また、RPCと違い、ユーザーがプロシージャ名や特定のパラメーターを、特定の順序で知る必要もありません。

ただし、REST APIの設計には欠点もあります。RESTでは、セッション内などで状態を維持できなくなり、新しい開発者が使用するのがより難しくなることがあります。また、APIを構築する前に、REST APIがRESTfulになる条件と、これらの制約が存在する理由を理解しておくことも重要です。結局のところ、なぜそれがその方法で設計されているかを理解していないと、気が付かないうちに努力を無駄にしてしまうことがあるのです。

REST APIの設計について理解する

「RESTful」を謳うAPIは数多くありますが、フィールディング博士が提唱する要件や制約の前提に達していないものがほとんどです。REST APIの設計がプロジェクトに適したAPIのタイプであるかどうかを判断する際に、注意すべき主な制約が6つあります。

クライアント/サーバー(Client-Server)

クライアント/サーバー制約は、「クライアントとサーバーは互いに分離し、それぞれ個別に進化すべきである」という概念にもとづいています。別の言葉で言えば、サーバー上のデータ構造やデータベース設計のいずれにも影響を与えることなく、モバイルアプリケーションに変更を加えることができるということです。同時に、モバイルクライアントに影響を与えることなく、データベースやサーバーアプリケーションに変更を加えられることも必要です。これにより、問題が分離できるため、各アプリケーションの独立した成長と拡張が可能になり、組織が急速かつ効率的に成長できるようになります。

ステートレス(Stateless)

REST APIはステートレスです。これは、呼び出しがそれぞれ独立して実行され、各呼び出しには、その呼び出しを正常に完了するために必要なすべてのデータが含まれていることを意味します。REST APIは、呼び出しに対する動作の決定にサーバーまたはセッションに格納されているデータに依存せず、呼び出しそのものが提供するデータにのみ依存します。呼び出しの実行時に、識別情報はサーバーに保存されません。代わりに、各呼び出しそのものに、APIキー、アクセストークン、ユーザーIDなど、必要なデータが含まれています。これにより、APIの信頼性を向上させることもできます。呼び出しの実行に必要なすべてのデータを保持することによって、オブジェクトの作成時にサーバーの状態を含む一連の呼び出しに依存することがなく、そのため部分的な失敗もしないためです。その代わりとして、メモリ要件を低減し、アプリケーションを可能な限りスケーラブルに保つため、RESTful APIでは、あらゆる状態がサーバーではなくクライアントに保存されている必要があります。

キャッシュ(Cache)

ステートレスなAPIは、大量の着信および発信呼び出しを処理することでリクエストのオーバーヘッドを増やすことができるため、REST APIはキャッシュ可能なデータの格納を促進するように設計する必要があります。つまり、応答は、データがキャッシュ可能である場合にデータを特定の時間(期限)まで格納できること、またはデータがリアルタイムである必要がある場合にクライアントにより応答がキャッシュされないことを示す必要があるということです。この重要な制約を有効にすることで、APIとの交信の回数を大幅に削減し、内部サーバーの使用量を減らすことができるだけでなく、最も高速でより効率的なアプリを提供するために必要なツールを、APIのユーザーに提供することができます。キャッシュは、クライアント側で実行されることに留意してください。アーキテクチャ内に一部のデータをキャッシュして全体的なパフォーマンスを実行することもできますが、その目的は、処理の方法と、クライアントでデータを一時的に格納するかどうかの指示をクライアントに出することです。

統一インタフェース(Uniform Interface)

サーバーからクライアントを切り離す際に重要なのが、統一インタフェースです。統一インタフェースを持たせることで、アプリケーションのサービス、モデル、またはアクションをAPIレイヤー自体に密接に結合させることなく、アプリケーションの独立した進化が可能になります。統一インタフェースにより、クライアントとサーバーの双方のアーキテクチャ上のバックエンドに関係なく、クライアントは単一の言語でサーバーと通信できます。このインタフェースは、URIリソース、CRUD(作成、読み取り、更新、削除)、およびJSONでのHTTPの使用など、クライアントとサーバー間に変更のない標準化された通信方法を提供する必要があります。

レイヤー化されたシステム(Layered System)

その名のとおり、レイヤー化されたシステムとは、レイヤーで構成されたシステムです。各レイヤーには特定の機能と役割があります。Model View Controllerフレームワークの場合を考えると、各レイヤーにはそれぞれの役割があり、それぞれ、データの形成方法を含むモデル、着信アクションに注力するコントローラ、および出力に注力するビューがあります。各レイヤーは分離されていますが、相互に作用するものでもあります。REST APIの設計でも同じ原則が当てはまり、アーキテクチャの各レイヤーが連携して階層を構築し、よりスケーラブルでモジュール化されたアプリケーションを作成します。

また、レイヤー化されたシステムでは、レガシーシステムをカプセル化してアクセス頻度の低い機能を共有の媒介に移動し、使用頻度の高い最新コンポーネントをレガシーシステムから隔離することもできます。さらに、レイヤー化されたシステムにより、テクノロジーやサービスの進化に合わせてシステムをアーキテクチャの内外に自由に移動できるため、さまざまなモジュールを可能な限り疎結合しておくことで、柔軟性と寿命を向上させることができます。レイヤー化されたシステムを使用すると、プロキシレイヤー(またはその他のレイヤー内)で攻撃を阻止して、実際のサーバーアーキテクチャへの侵入を防ぐため、非常に大きなセキュリティ上のメリットがあります。プロキシでレイヤー化されたシステムを利用したり、単一のアクセスポイントを作成したりすることで、アーキテクチャの重要かつより脆弱な部分をファイアウォールで保護し、クライアントによる直接のアクセスを防ぐことができます。セキュリティは、単一の「すべてを止める」ソリューションではなく、特定のセキュリティチェックの失敗やバイパスの可能性を考慮して、複数のレイヤーで構成されていることに留意してください。このように、より多くのセキュリティをシステムに実装できれば、被害を及ぼす攻撃を防げる可能性がより高くなります。

コードオンデマンド(Code on Demand)

コードオンデマンドは、おそらく6つの制約のうちではあまり知られておらず、唯一のオプション制約です。コードやアプレットをAPI経由で送信し、アプリケーション内で使用できるようにします。基本的には、これにより独自のコード構造のみに依存しない、スマートなアプリケーションが作成できます。ただし、Code on Demandは時代を先取りしていたこともあり、Web APIが複数の言語で使用され、コードの送信によりセキュリティの問題や懸念が生じるため、あまり採用されてきませんでした。(たとえば、ディレクトリが書き込み可能でなければならず、ファイアウォールで通常制限されるようなコンテンツが許可されている必要がありました。)

REST(Representational State Transfer)は、こうした制約によって構成されている理論です。これらを改めて見てみると、後に続く制約が前の制約に重ねて構築され、最終的には非常に複雑かつ、強力で柔軟なアプリケーションプログラムインタフェースが作成されていくのが分かります。ただし、最も重要なのは、これらの制約によって、私たちがワールドワイドウェブのブラウザでページにアクセスするのと似た動作をする設計が構成されるということです。これにより、アーキテクチャではなく自身が返す表現によって指示を受けるAPIと、アーキテクチャ的にはステートレスでありながら、その表現に応じてアプリケーションの状態に指示を出すAPIが作成されます。