RESTについて勉強する - RESTとは?
こんにちは、nekonote-civ です(ΦωΦ)
現在フィヨルドブートキャンプで勉強している内容にREST
という概念が登場してきました。
こちらもWebシステムについて学ぶ際に非常に重要だということで、主に下記の書籍を参考にしながら整理していきたいと思います。
Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus) | 山本 陽平 |本 | 通販 | Amazon
目次
アーキテクチャスタイルとは?
「Webを支える技術」の中ではRESTのことを「Webのアーキテクチャスタイル」と表現していました。
では「アーキテクチャスタイル」ってなんぞや?ということで掘り下げてみると、以下のような記述がそれぞれ確認できました。
[Webを支える技術]
アーキテクチャスタイルは別名「(マクロ)アーキテクチャパターン」とも言い、複数のアーキテクチャに共通する性質、様式、作法あるいは流儀を指す言葉です。 アーキテクチャスタイル には、たとえばMVC(Model-View-Controller)やパイプ&フィルタ(Pipe and Filter)、イベント システム(Event System)などがあります。
アプリケーション概要を定義するには?(3/3) - @IT - ITmedia
アーキテクチャ スタイル - Azure Application Architecture Guide
上記から、「アーキテクチャスタイル」=「複数のアーキテクチャに共通している性質や様式をまとめた設計における要件(スタイル)の集まり」のようなものであると分かります。
(アーキテクチャ = 構造、骨組み)
色々なシステム構造がある中で、「この構造で動作する仕組みは色々な所で使えるな!」とパターン化しておくことで、アーキテクチャの設計段階における車輪の再発明を防ぎ、効率的で安全なシステムが作れる、という感じでしょうか。
リソースとは?
もう一つ、同書には「リソース」が重要な概念の一つである、とも記述されています。
リソース(Resource)は直訳すると「資源」ですが、ことRESTにおいてはWeb世界における仕組みのことですから、資源ではちょっと意味が分かりづらいです。
こちらについてはMDNの下記が個人的に分かりやすかったです。
ウェブ上のリソースの識別 - HTTP - MDN Web Docs
HTTP 要求の対象は「リソース」と呼ばれ、その本質は細かく定義されていません。ドキュメント、写真、その他の何にでもなりえます。 それぞれのリソースは、リソースを特定するために HTTP の至るところで使用される Uniform Resource Identifier (URI) で特定されます。
「Webの世界でHTTP等により要求される対象は大体リソース」であり、また「URIで特定される」のですから、「一意の名前がついている」という前提が必要です。
(URIについては別途まとめる予定です)
ということで、ドキュメント(HTML, txt等)、写真(jpg, png等)などによらず、一意の名前を持ったWeb上にあるあらゆる情報がリソースであると言えるかと思います。
RESTとは?
では、改めて本題である「REST」について見ていきます。
RESTとは「Representational State Transfer」の略であり、WebAPIの定義に使用されるアーキテクチャスタイルとのことです。
アーキテクチャスタイルという概念がどんなものかは何となく分かってきましたが、RESTは一体どのような設計の性質があるのでしょうか。
こちらも同書に記載の主な項目を見ながら考えてみます。
クライアント/サーバ
Webの世界では、主にサービスを利用する側のクライアント(ブラウザ側)がネットワークを介してサーバに対して通信していますが、これを「クライアント/サーバ」と呼びます。
「クライアントサーバ」「クライアントサーバモデル」などとも呼ばれているようです。
サーバは常にクライアントからの要求を待ち、そのリクエストに応じて処理を行う、という構造です。
これは至ってシンプルであり、クライアントとサーバが分離して処理出来るため、サーバはサーバ側の処理だけに気を使えば良いことになります。
「関心分離の法則」に近い感じでしょうか。
ステートレスサーバ
ステートレス(Stateless)とは「状態(state)を持たない」ことであり、サーバ側がクライアントの状態を管理しないことを指します。
そもそも「状態を管理する」とは何でしょうか?
例えば、Cookieを使ったセッション管理が例に挙げられます。
Cookieはサーバがブラウザに状態を管理するための識別子を渡し、それを使ってブラウザがサーバにアクセスすることで、まるで「サーバがそのユーザを記憶している」ような形でログイン機能などを提供することが出来ますね。
ではステートレスはどうなっているかというと、これらのような状態を一切持たないことにより、一度のリクエストの処理が終わった時点でサーバの作業は終了し、すぐに計算リソースを開放します。
「さっきの〇〇さんからの要求だな」というようなことは判断せず、それぞれ毎のリクエストを新規の来訪者として取り扱い、終わったらその人のことはさっぱり忘れるということですね。
とはいえ制約に反するからとセッションとか絶対利用しない!というのは困る時もあるので、そこはメリット・デメリットを理解して設計することになります。
キャッシュ
キャッシュは、同じ情報などを取り扱う場合に既に持っている情報を用いて不要なやり取りを防ぐ仕組みです。
これにより、ユーザの待ち時間を軽減したり、当然不要な処理をしませんからパフォーマンスも上がります。
また、Roy Thomas Fielding の論文を見る限り、ここでのキャッシュは「クライアント側で保持するキャッシュ」を指していると思います。 www.ics.uci.edu
その為、古いキャッシュを参照してしまうことにより、古い情報を取得してしまう、というデメリットは考えられそうです。
統一インタフェース
統一インタフェースとは、決められた原則に従うように限定されたインタフェースであり、定義された仕組み以外を利用しないようにします。
例えばHTTPには「GET」「POST」などのメソッドが9個ほど定義されており、これ以外は利用できません。
ここを統一することにより、下記のメリットが享受できることになります。
サーバ
定義通りに設計することで、その定義を利用した全ての利用者に正しくレスポンスを返すことが出来る。クライアント
定義に合わせてリクエストすることで、どのアプリケーションを利用していても、どのサーバ宛であっても定義に則ったレスポンスを受け取れる。
規格が乱立していたらどう要求したら良いかも分からないし、受け取る側もどのような要求が来るかわからないから準備できないわけですね。
階層化システム
クライアントとサーバの間にロードバランサーやプロキシサーバなどを挟むことにより、負荷分散を行ったりアクセス制限ができたりします。
[クライアント] <--------> [プロキシサーバ] <--------> [サーバ]
また、HTTPが利用できないようなレガシーなシステムとクライアントの間にHTTPを利用できるサーバを挟むことにより、クライアント側は他のサーバと同じようにRESTを用いた通信を行うことが出来ます。
[クライアント] <--------> [HTTPが出来るサーバ] <--------> [古いサーバ]
このような階層構造を用いることが出来るのも、「統一インタフェース」を採用していて常に要求の形式が決まっているおかげということです。
コードオンデマンド
「オンデマンド(On Demand)」とは、要求があったらその要求に応じたコンテンツなどを提供することを指します。
VOD(Video On Demand)が良い例ですが、これはユーザが見たい時に要求すればいつでも動画を見ることが出来る仕組みですよね。
ではコードオンデマンドはどういうものかというと、プログラムコードをサーバからダウンロードしてクライアント側で実行する仕組みを指します。
「JavaScript」「Flash」「Java アプレット」あたりがそういう仕組みのようです。
これによりリッチなWebサービスを提供することが出来ますが、サーバからはデータではなくプログラムコードが送られる為、それを外部から監視/分析することが難しい、つまり可視性が低下してしまうようです。
ちょっとここの「可視性が低下する」とどのようなデメリットがあるのか記事を書き始めた時にピンとこなかった為、フィヨルドブートキャンプ内で質問をしつつ自分の考えをまとめてみました。
ちょっと長くなってしまうのでこちらについては次回の記事で公開します!
まとめ
ここまでをまとめると、上述のような様々な性質を持ったものが「REST」の根本的な部分でありますが、これを全て適用しないとRESTではない、というわけでもなさそうです。
ステートレスの時に出したセッションの話がまさにそれですね。
それぞれの内容を上手く組み合わせて、システムに落とし込むのが設計者の技術の見せ所なのかなと思います。
正直書いていて「階層化システム」とか「統一インタフェース」のあたりがふわっとしたので、ここはもう少し掘り下げて理解出来るようにしたいですね。
次回は「RESTにおける「コードオンデマンド」の可視性の低下のデメリットとは?」という素朴な疑問から始まったRESTにおける可視性について調査した内容を書いていきます!