『REST API』とは

RESTとは、REpresentational State Transferの略語であり、直訳すると「状態(ステート)を具体的に宣言して引き渡す」となります。REST APIは、既存プロトコルの利用を前提に設計されています。そのため、開発者はREST APIを利用すれば、ライブラリやソフトウェアの追加開発が必要なくなります。ほぼすべてのプロトコルで使用できますが、Web APIとして使用する場合にはHTTP(Hyper Text Transfer Protocol)が一般的です。REST APIの設計思想は、ロイ・フィールディング博士が2000年に彼の博士論文の中で提唱しました。
特筆すべきは、その驚くほど柔軟なレイヤーです。データは、メソッドやリソースに縛られません。そのためREST APIは、「数種類の呼び出し処理」や「異なるデータ形式での返信」が可能です。さらに、ハイパーメディアを正しく実装することにより、構造的な変更も実現できるようになります。(注記:ここに記しているRESTは、Dr. Roy T. Fieldingが提唱した「Client-Server」「Stateless」「Cache」「Uniform Interface」「Layered System」「Code-On-Demand」に基づいています。現在、多く流通している「REST APIの四原則」に比べても、より高い可用性や発展性の実現を前提としています)。

ITサービスに対する、自社内からの要望とお客様の多様なニーズの両方を満たせるのは、REST APIが備えているこの自由度と柔軟性のおかげなのです。SOAPと違い、RESTは特定のプロトコルに制約されません。クライアントの要求に応じて、XML、JSON、YAML、その他あらゆる形式で応答することができます。またRPCとも違い、ユーザは処理を実行するために、プロシージャ名やパラメータ、それらの順序を把握する必要もありません。

ただし、REST APIの設計には欠点もあります。RESTでは、セッション内などの状態(ステート)を維持する機能が失われることがあり、開発に後から参加する者には使いづらくなることがあるのです。APIを開発・展開する前に、このREST APIの制約条件が、これから構築するアーキテクチャやサービスに与える影響を把握しておくことは重要です。設計の背景と理由を理解していないと、気づかないうちに努力が無駄になってしまうことがあるのです。

REST APIの設計

『RESTful』を謳うAPIのほとんどが、フィールディング博士が提唱した要件や制約を満たしていないという事実があります。着手しているプロジェクトにREST APIが適してるかどうかを判断する際に、注意すべき6つの制約条件を以下に紹介します。


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

クライアントサーバ制約とは、「クライアントとサーバを分離し、それぞれ個別に進化させる」という考え方です。つまり、サーバ上のデータ構造やデータベース設計に影響を与えることなく、モバイルアプリ(クライアント)に変更を与えられなければなりません。同時に、モバイルアプリに影響することなく、データベースを更新したり、サーバ上のアプリケーションのアップデートができなければなりません。問題の分離ができるため、各アプリケーションが互いに独立しながら更新・拡張が可能になります。これにより、問題の検知と発見が迅速化され、高頻度なアップデートも実現できるため、オペレーションの効率化やビジネスの成長を強力にサポートすることが可能になるのです。


ステートレス(Stateless)

REST APIはステートレスです。各々の呼び出しが独立して実行され、各呼び出しにはそれ自体を正常に完了するために必要なすべてのデータを含んでいます。REST APIでは、呼び出し(call)が実行内容を決定するため、サーバやセッションに保存されているデータに依存しません。むしろ、その呼び出しに応答して提供されるデータだけに依存します。また、呼び出し実行時の識別情報はサーバに保存されません。その代わり、APIキーやアクセストークン、ユーザIDなどの必要なデータは、各コールに含まれています。APIに呼び出し実行に必要なすべてのデータを持たせることで、オブジェクト作成のための呼び出し順序などに依存しなくなり、余分なエラーを回避することができます。つまり、APIの信頼性を高めることにも役立つのです。そのためREST APIでは、必要なメモリを減らし、かつ、アプリケーションに最大限の拡張性を持たせるため、状態(ステート)をサーバではなくクライアント側に持たせることになります。


キャッシュ(Cache)

ステートレスなAPIだと大量の呼び出し処理(発信と着信の両方)によってリクエストのオーバーヘッドが増大する可能性があります。そのためREST APIは、キャッシュ可能なデータの保存を推奨するように設計する必要があります。データがキャッシュ可能な場合、応答データが一定時間まで保存可能なとき(expires_at)、または応答データがリアルタイムであることが必要なときは、クライアント側にキャッシュされないことを明示することは必須でしょう。それ以外は基本的に、キャッシュはクライアント側に保存されることを念頭に置いてください。アーキテクチャ内に一部データをキャッシュさせて全体パフォーマンスを実行することもできますが、そういった処理は①クライアントによる処理の内容を指示する場合と②クライアントにデータを一時的に保存することを指示する場合に限定するべきでしょう。


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

サーバとクライアントを切り離すカギは、統一インタフェースを持たせることです。統一インタフェースを採用することにより、API層とアプリケーションの密結合を回避でき、アプリケーションのサービス、モデルそしてアクションの独立的な進化を可能にします。統一インタフェースによりサーバとクライアントは、双方のアーキテクチャのプラットフォームに関係なく、単一言語で通信できるようになります。このインターフェースには、クライアントとサーバ間で通信するための「不変」かつ「標準化された」手段が必要になります。URIやCRUD(Create、 Read、 Update、 Delete)、JSONをHTTPで通信する方法が例として挙げられます。


階層システム(Layered System)

階層システムとは、その名のとおり、レイヤー構成されたシステムです。各レイヤーは特定の機能と役割を持っています。MVC(モデル・ビュー・コントローラ)を例に考えてみましょう。MVCでは、各レイヤーはそれぞれ独自の役割を持っています。具体的には、システムの設計や機能などのロジックを担当する『モデル』、データや情報を表現する『ビュー』、ユーザのリクエストにレスポンスを返す『コントローラ』となります。各レイヤーは、独立しながら相互作用もしています。REST APIの設計でも同じ原理が当てはまります。複数のレイヤーが独立しつつ相互連携してアーキテクチャを構築することで、高い拡張性のあるモジュール化されたアプリケーションを作成することができるのです。

また階層システムではレガシーシステムをカプセル化し、あまり使わない機能を共有の媒介に移動させ、使用頻度の高いコンポーネントをレガシーシステムから隔離・保護することもできます。さらに階層システムは、テクノロジーやサービスの進化に合わせてシステムをアーキテクチャの内外に自由に出し入れできます。異なるモジュール間を疎結合に保つことで、柔軟性と寿命が向上します。

階層システムは、プロキシレイヤーなどで外部からの攻撃を阻止し、実際のサーバーアーキテクチャへの侵入を防ぐため、セキュリティにも大きなメリットがあります。プロキシを使った階層システムの利用や、シングル・アクセス・ポイントを用意することで、アーキテクチャの重要かつ脆弱な部分をファイアウォールの背後に置き、クライアントによる直接アクセスを不許可にすることができます。セキュリティは『停止(stop_all)』に頼ればよいというものではありません。セキュリティ・チェックが失敗したり、(リクエストが)バイパスされたりする可能性を考慮して、複数レイヤーを持つことが重要です。異なる特徴を持つ複数のセキュリティをシステムに実装することで、有害な攻撃に晒される可能性を最小化しなければなりません。


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

コードオンデマンドは、6つの制約のうちで最も知られておらず、唯一のオプショナルな制約です。コードやアプレットをAPI経由で送信しアプリケーション上で動かせるようにする、という制約です。これにより、独自のコーディングに依存しない、スマートなアプリケーションが作成できます。

しかし、Web APIが複数言語で使用されており、コードの送信によるセキュリティの懸念が生じるため、コードオンデマンドの大規模アプリケーションへの採用は進んでいません(もちろん、Global Site Tagを始めとするブラウザ上で動いているJavaScriptは、サーバから受け取ったプロシージャをクライアント側で実行するため、コードオンデマンドと言えるでしょう)。時代を先取りしすぎていたかもしれません。

Summary

REST(REpresentational State Transfer)は、上記の6つの制約を組み合わせて構成されています。改めてこれらの制約を見ると、それぞれの制約が前の制約の上に積み重なることで、とても複雑だが強力かつ柔軟なAPIを作り上げていることが理解できます。しかし最も重要なのはこれらの制約が、ブラウザでWebページにアクセスすることと同じように、簡便に動くアプリケーションやサービスを構成しているという事実です。これにより、アーキテクチャに左右されないAPIの構築が可能になります。アーキテクチャ的には、ステートレスでありながら表現に応じてアプリケーションの状態(ステート)に指示を出すAPIが作成されるのです。