RESTアーキテクチャの概要

現代のWebサービスを支える基礎概念へようこそ。一般にRESTとして知られるRepresentational State Transferは、Webサービスを構築するために用いられる一連の制約を定義したアーキテクチャスタイルです。Roy Fieldingが博士論文で提唱したRESTは、標準規格やプロトコルではなく、高レベルの設計思想です。RESTは、コンピューターシステムがインターネットを介して通信するための標準化された方法を提供し、異なるアプリケーション同士が円滑に相互理解できるようにします。RESTの原則に従うことで、開発者はスケーラブルで堅牢性が高く、長期的に保守しやすいシステムを構築できます。

このアーキテクチャスタイルの中心にある原則は、すべてがリソースであるという考え方です。リソースとは、クライアントが操作する可能性のあるあらゆる情報やデータエンティティを指し、顧客レコード、ブログ記事、金融取引などが該当します。RESTでは、確立された堅牢なWebのインフラストラクチャを活用し、システムはステートレスに通信すべきだとされます。つまり、ほぼ例外なくHypertext Transfer Protocolなどの標準インターネットプロトコルを利用して、情報を要求するクライアントと、それをホストするサーバーの間でデータを送信します。

RESTを理解するには、アクションについて考えるのではなく、物について考えるように発想を転換する必要があります。従来のリモートプロシージャコールアーキテクチャでは、システム同士が実行すべき関数を指示することで通信していました。一方、RESTfulアーキテクチャでは、リソースの現在の状態を表す表現を転送することで通信します。クライアントがリソースを要求すると、サーバーはその特定の時点におけるリソースを表すペイロードを、JavaScript Object NotationやExtensible Markup Languageのような広く理解されている形式で返します。

リソースとURIの概念

RESTはリソースを中心に構成されるため、これらのリソースを正確かつ一貫して識別することが極めて重要です。RESTアーキテクチャでは、すべてのリソースにUniform Resource Identifierが割り当てられ、Web上での一意のアドレスとして機能します。この識別子は、論理的で階層構造を持ち、人間の開発者が理解しやすいものでなければなりません。適切に設計されたアドレス構造により、アプリケーションプログラミングインターフェースの利用者は、複雑なドキュメントを暗記しなくても、関連データの所在を予測できます。

業界標準のベストプラクティスでは、これらのリソースに複数形の名詞を使用して名前を付けます。アクションを表す動詞をアドレスに含めるのではなく、アドレスではエンティティそのものだけを表すべきです。たとえば、従業員レコードを管理するインターフェースを構築する場合、ベースアドレスは単に /employees とします。この名詞ベースのアプローチにより、アドレスが簡潔になり、実行される操作ではなくデータの対象そのものに完全に焦点を当てられます。/get-employees や /create-employee のように動詞を使用することは、REST設計原則に対する根本的な違反です。

クライアントがリソースのコレクションではなく、単一の特定リソースを操作する必要がある場合は、一意の識別子をアドレスパスに追加します。データベース上の識別番号が42である従業員のレコードにアクセスする場合、適切なアドレスは /employees/42 となります。この階層構造は、異なる種類のリソース間の関係を表すように拡張できます。その特定の従業員の給与記録を表示する必要がある場合、アドレスは論理的に /employees/42/payrolls へ拡張されます。

RESTにおける標準HTTPメソッド

Uniform Resource Identifierがデータのアドレスを提供するのに対し、HTTPメソッドはアクションを提供します。RESTは、Hypertext Transfer Protocolに組み込まれた標準メソッドを活用して、対象リソースに対して実行する操作をサーバーに指示します。アドレスとアクションを分離することで、RESTfulインターフェースは非常に予測しやすくなっています。日常的に使用する最も一般的な4つのメソッドは、GET、POST、PUT、DELETEです。

GETメソッドは、情報の取得専用に設計されています。クライアントがGETリクエストを発行すると、リソースをどのような形でも変更せずに、その表現を返すようサーバーに要求します。このメソッドは、安全かつ冪等であると定義されています。安全なメソッドとはサーバーの状態を変更しないメソッドを指し、冪等なメソッドとは、まったく同じリクエストを10回送信しても、1回送信した場合とサーバー上でまったく同じ結果になるメソッドを指します。GETリクエストは、単に文書を読み取る操作だと考えることができます。

POSTメソッドは、サーバー上にまったく新しいリソースを作成するために使用されます。クライアントがコレクションのアドレスにPOSTリクエストを送信すると、新しいエンティティのデータを含むペイロードがリクエストに含まれます。GETメソッドとは異なり、POSTは安全でも冪等でもありません。同一のPOSTリクエストを複数回送信すると、サーバー上に複数の別個のリソースが作成されます。サーバーはペイロードを処理し、新しいリソースに一意の識別子を生成して、データベースに保存します。

既存のリソースを変更するには、開発者はPUTメソッドとDELETEメソッドを使用します。PUTメソッドは、リクエストのペイロードで提供された新しい状態によって、現在の状態を完全に置き換えることでリソースを更新します。リソースが存在しない場合、PUTリクエストによって作成されることもありますが、通常は完全更新に使用されます。DELETEメソッドは、その名が示すとおり、指定されたリソースをサーバーから恒久的に削除するよう要求します。PUTとDELETEはいずれも冪等であることを意図して設計されています。つまり、同じ特定のリソースを更新または削除する同一のリクエストを複数回送信しても、最初のリクエスト後とまったく同じ状態になります。

操作とビジネスロジックの対応付け

ソフトウェアエンジニアリングにおいて、永続ストレージに必要な基本操作は、Create、Read、Update、Deleteです。RESTは、これらのデータベース操作と、先ほど説明したHTTPメソッドを直接対応付けます。CreateはPOST、ReadはGET、UpdateはPUT、DeleteはDELETEメソッドにそれぞれ完全に対応します。この標準化された対応関係により、開発者は基盤となるデータモデルを理解すれば、インターフェースとのやり取りの方法を直感的に把握できます。

小売書店向けの在庫管理システムを構築する実際的なビジネスシナリオを考えてみましょう。このシステムの中核となるリソースは書籍です。出版社が新しい小説を刊行すると、在庫管理担当者はそれをシステムに追加する必要があります。クライアントアプリケーションは、タイトル、著者、価格などの書籍情報をまとめ、/booksアドレスを対象とするPOSTリクエストに含めて送信します。サーバーはこれを受け取り、レコードを作成し、通常は新しく割り当てた識別番号を返します。

その後、従業員が特定の書籍の価格が誤って入力されていることに気付きました。これを修正するため、クライアントアプリケーションは、/books/892のような特定のリソースアドレスにPUTリクエストを発行します。このリクエストのペイロードには、完全に修正された書籍情報が含まれます。サーバーはその識別子を持つ書籍を検索し、既存のデータを修正後のデータで置き換えます。その書籍が絶版になり、アクティブなカタログから完全に削除する必要がある場合、クライアントは同じ特定のアドレスにDELETEリクエストを送信します。

左側に4つのCRUD操作を配置し、矢印で右側の対応するHTTPメソッドGET、POST、PUT、DELETEに接続し、書店の在庫管理システム用のURI例を示した視覚的な対応関係図

ステートレス性とサーバーレスポンス

RESTで最も重要な制約の1つは、クライアントとサーバー間のすべてのやり取りが完全にステートレスでなければならないことです。これは、サーバーが個々のリクエスト間でクライアントのセッションに関する情報を保存してはならないという意味です。クライアントが開始するすべてのリクエストには、サーバーがその操作を理解して実行するために必要なすべてのコンテキスト、認証情報、データが含まれていなければなりません。サーバーは、受信する各リクエストを完全に独立したトランザクションとして扱い、それ以前にどのようなリクエストがあったかを認識しません。

この厳格なステートレス性こそが、RESTアーキテクチャに非常に高いスケーラビリティをもたらします。サーバーはユーザーセッションを追跡するためにメモリを割り当てる必要がないため、相当量の計算リソースを解放できます。さらに、ロードバランサーの背後にある大規模な分散システムでは、大規模なクラスター内のどのサーバーでも、どのクライアントからのリクエストでも処理できます。1台のサーバーがクラッシュしても、セッションデータは完全にクライアント側に保存されているため、ユーザーがセッションデータを失うことなく、別のサーバーが直ちにその役割を引き継げます。

これらの独立したトランザクションの結果を伝えるために、サーバーは標準のHTTPステータスコードを使用します。これらの3桁の数値によって、操作が成功したか失敗したかをクライアントに即座に通知できます。200番台のコードは成功を示し、たとえば200 OKや201 Createdなどがあります。400番台のコードはクライアントエラーを示します。これは、リクエストの形式が正しくないか、クライアントが存在しないリソースを要求したことを意味します。最後に、500番台のコードは、完全に正当なクライアントのリクエストを処理しようとした際に、サーバーで予期しないエラーが発生したことを示します。

REST設計におけるよくある間違い

RESTは広く採用されているにもかかわらず、開発者はその基本原則に反する設計ミスを頻繁に犯します。最も一般的な間違いは、リソースのアドレスに動詞を組み込むことで、リモートプロシージャコールの習慣に逆戻りしてしまうことです。/add-bookや/update-userのようなアドレスは、インターフェースの一貫性を損ないます。HTTPメソッドがすでにアクションを表しているため、アドレスに動詞を追加すると冗長さと混乱が生じます。アドレスは厳密に名詞を識別し、動詞はHTTPメソッドが処理するべきです。

もう一つの重大な間違いは、データの変更や削除にGETメソッドを誤って使用することです。開発者が、/users/5/deleteのようなアドレスを作成し、クライアントにGETリクエストでアクセスするよう指示することがあります。これは非常に危険です。標準的なWebインフラストラクチャでは、GETリクエストは安全な操作として扱われるためです。WebブラウザはGETリクエストを先読みし、キャッシュサーバーはそれらを複製し、検索エンジンのクローラーは自動的にインデックスに登録します。GETリクエストが削除を実行する場合、サイトを巡回する単純なWebクローラーによって、データベース全体が誤って消去される可能性があります。

最後に、複数形の使い方に一貫性がないと、インターフェースを利用する開発者に負担が生じます。すべてのユーザーを取得するアドレスが/usersのように複数形である一方、アカウントを取得するアドレスが/accountのように単数形だと、利用者は綴りを思い出すために常にドキュメントを参照しなければなりません。業界で認められている標準は、コレクションと個々のリソースのすべてにおいて、複数形の名詞だけを使用することです。一貫性は、適切に設計されたRESTインターフェースの証であり、長期にわたって直感的で統合しやすい状態を維持することにつながります。

レッスンのチェックポイント

1. Webサービスの文脈において、RESTは何を意味しますか?

2. REST URIでリソース名を付ける際の業界標準の慣行は、次のうちどれですか?

3. 情報の取得専用に設計され、安全かつべき等性があると見なされる HTTP メソッドはどれですか?

4. クライアントアプリケーションは、サーバーにまったく新しいリソースの作成をどのように要求すべきですか?

5. REST において、ステートレス性の制約がサーバーアーキテクチャにとって重要なのはなぜですか?

6. リソースの削除にGETメソッドを使用すると、どのような危険な結果が生じますか?