はじめに
Webアプリケーションを作成するにあたり、必要になるREST APIという仕組みについて学習をしたのでアウトプットします
REST APIとは
RESTのルールに従ったAPIのことです
「REST???」
「API???」
全部わかるように解説していきます
APIとは
APIとはお客さんと厨房の橋渡しをする定員さんのようなものです
レストランの例えで理解するAPI
注文の流れ
- お客さん:「カレーください」と注文する
- 店員:注文を厨房に伝える → 出来上がった料理を持ってくる
- お客さん:厨房の中身を知らなくても、決められた方法で料理を受け取れる
Webでの対応関係
-
お客さん → クライアント
スマホやPC、ブラウザなど -
店員 → API
クライアントからの注文を正しい形でサーバーに渡し、結果を返す -
厨房 → サーバー
リクエストを処理して結果を用意する
用語の対応
- 「カレーください」と注文すること → リクエスト
- 「カレーをください」という注文内容そのもの → URL
- 厨房から料理が届くこと → レスポンス
- お客さんの側 → クライアントサイド
- 店側(店員+厨房) → サーバーサイド
RESTとは
REST(Representational State Transfer)の設計原則に従った設計や実装を指す言葉です。
要はRESTというルールを守った設計が好ましいですよ〜ってことです
RESTのルール
- クライアント/サーバー
- ステートレス
- キャッシュ制御
- 統一インターフェース
- 階層化システム
- コードオンデマンド
クライアント/サーバーを分けましょう(ルール1)
クライアント/サーバー分離の特徴
1. 役割を明確化することができる
-
クライアント(UI側)
- 画面表示、ユーザー操作の処理を担当
- APIを呼び出してデータを取得/送信する役割
-
サーバー(データ側)
- ビジネスロジックやデータ管理を担当
- データの永続化、認証/権限チェックなどを行う
↪︎ 役割が明確になり、開発・保守が容易になる
2. クライアントがトリガー、サーバーは受け身
- RESTの基本設計では、クライアントがリクエストを送信し、サーバーはそれに応答する
- 例:
- ボタンを押す → クライアントがAPIを呼ぶ → サーバーがレスポンスを返す
3. サーバーからのPushの存在
- 本来は受け身のサーバーだが、近年はプッシュ型通信も増えている
- WebSocket: 双方向通信(例: チャットアプリ)
- Server-Sent Events (SSE): サーバーからの一方向プッシュ
- Push通知: モバイル端末やブラウザ通知
4. 開発・運用上のメリット
- フロントエンドとバックエンドを独立して開発可能
-
複数のクライアントから共通のAPIを利用可能
- Web、スマホアプリ、外部サービスなど
- API仕様を守ればクライアントを修正せずにサーバーを改善できる
クライアント(UI・アプリ) ⇄ サーバー(データ・ロジック)
- 画面表示 - データ管理
- 入力受付 - 認証・権限
- API呼び出し - 処理実行
階層化システムにしましょう(ルール2)
1. 概要
- 階層化システムとは、システムを複数の層(レイヤー)に分けて構築する設計手法
-
多層アーキテクチャとも呼ばれ、代表的な構成は以下のようになる:
- Web(プレゼンテーション層): ユーザーにUIを提供
- AP(アプリケーション層): ビジネスロジックを処理
- DB(データ層): データの永続化と管理
2. メリット
-
役割の明確化
各コンポーネントに責務を割り当てることで、設計や保守が容易になる。 -
進化と再利用が容易
UIを変えてもビジネスロジックはそのまま利用できるなど、機能の独立性が高い。 -
セキュリティ強化
中間層を設けることで、不正アクセスや内部構造の秘匿化が可能。 -
スケーラビリティ
必要な層を水平・垂直にスケールさせることで、大規模アクセスにも対応できる。
3. デメリット
-
オーバーヘッドの発生
層ごとに処理や通信が入るため、レスポンスが遅くなる可能性がある -
ユーザー体験の低下
遅延がユーザーに見えると、応答が悪く感じられる。
4. 改善策
-
キャッシュの活用
頻繁に利用するデータや処理結果をキャッシュすることで、レスポンスを改善できる。
キャッシュ制御しましょう(ルール3)
キャッシュ制御とは?
- キャッシュ = 一度取得したデータを手元に保存しておいて再利用する仕組み
- クライアントはサーバーからのレスポンスをキャッシュできる
- サーバーはレスポンスに「このデータはキャッシュしていいか/いつまで有効か」を明示的に示せる
- または暗黙的にキャッシュされることもある
どう役立つ?
- 毎回サーバーに取りに行かなくても、手元のデータをすぐ表示できる
効果
- 通信回数が減る
- 表示が速くなる(ユーザー体験の向上)
- サーバー負荷が減る(効率アップ)
- サービスが大規模になっても安定して動かしやすい(拡張性アップ)
例
- Webページを2回目に開いたら、画像やCSSがすぐ表示される
- SNSアプリで前に見た投稿をスクロールしたら、すぐ出てくる
メリット
- ユーザー体験の向上
→ページ表示が速くなる - リソース効率の向上
→ ネットワーク通信やサーバー処理が減る - 拡張性の向上
→ ユーザー数が増えても対応しやすい
デメリット
- 古いデータを返してしまうリスク
→ キャッシュが更新されないと最新じゃない情報が出る
→ システムへの信頼性が下がる可能性がある
コードオンデマンドしましょう(ルール4)
概要
サーバーがクライアントにコードを送って実行させる仕組み。
↪︎フロントエンドに最初から全部置かなくても、必要に応じて後から機能を追加できる。
代表例
- JavaScript
- Javaアプレット
- HTML更新
メリット
-
リリース後でも機能追加可能
→ ユーザーはアプリ更新不要、ページ更新だけで新機能を利用できる。 -
サーバー負荷を軽減
→ クライアント側で処理を実行させられる。
デメリット
-
評価・テストが複雑化
→ ブラウザや環境ごとに挙動が変わるため、多数の検証が必要。
例え(ゲームアプリ)
- 通常アップデート:アプリ自体を更新 → ストア再DL必須
- コードオンデマンド:サーバーから機能配布 → ゲーム内の更新ボタンで即追加
→ユーザーはコードを書かなくても機能が増える
→再インストール不要のアップデートが可能になる
ステートレスな設計をしましょう(ルール5)
ステートフルとは?
- サーバーが前の状態を覚えている方式
- 前回のやり取りを踏まえて次を処理する
例
- ショッピングサイトでログイン状態をサーバー側で保持
- 会話アプリで前のメッセージ内容をサーバーが覚えて次の返答をする
サーバーが記憶持ちで、クライアントはその記憶を頼りにやり取りできる
ステートレスとは?
- サーバーは前の状態を覚えない方式
- すべてのリクエストが独立していて、過去を知らなくても処理できる
仕組み
- サーバーに状態は保存しない
- 必要な状態はクライアント側に保存し、毎回リクエストに含める
例
- APIを叩くときに毎回
Authorization: Bearer トークン
を送る - 次のページのリンクに
page=2
などのパラメータを含める
↪︎サーバーは記憶喪失だけど、クライアントが全部必要情報を持ってくるから成立する
ステートレスのメリット
- 監視がシンプル
→ 単一のリクエストだけ見れば良い - 障害対応が楽
→ 問題のあったリクエストだけ直せば済む - スケールしやすい
→ サーバー間でセッション共有する必要がない
ステートレスのデメリット
- リクエストに重複データが増える
→ 毎回トークンや同じ情報を送る必要がある - アプリ制御が複雑化
→ 状態を全部クライアント側で管理するため、複数バージョンを同時提供すると制御が難しい
統一インターフェース(ルール6)
概要
RESTで一番大事なルール。
「クライアント(ブラウザやアプリ)とサーバーが、同じやり方で必ずやり取りする」という決まりごと。
→ これを守ることで、誰が作ったクライアントでも同じAPIを使える。
統一インターフェースは RESTの基本思想そのもの を体現していて、
開発者や利用環境が違っても「同じルールでアクセスできる」ことを保証する。
4つの制約
1. リソースの識別
- リソース = 名前をつけられるあらゆるもの(データ、サービス、状態など)
- URI でリソースを特定する(操作は含まない)
- 例:
- ドキュメント、画像、人、情報、サービス
- 抽象的なもの(4月1日の天気、最新の天気)
2. 表現を用いたリソース操作
- 表現 = リソースのある断面(スナップショット)
- クライアントとサーバーは表現をやり取りしてリソースを操作する
- 例:
- JSONやXMLで返ってくるレスポンス
- POSTで送るデータ(+認証情報など)
3. 自己記述メッセージ
- リクエストやレスポンスに「中身は何か」の説明が含まれる
- 具体例:
-
Content-Type: application/json
→ JSON形式だと分かる -
Authorization: Bearer xxx
→ 認証情報を含む
-
4. アプリケーション状態エンジンとしてのハイパーメディア(HATEOAS)
- レスポンスに「次にできる操作」へのリンクを含める
- 例:
- 検索結果レスポンスに次のページリンクがある
- クライアントはリンクを辿るだけで状態遷移できる
メリット
- システムアーキテクチャ全体が簡素化されて分かりやすい
- 提供するサービスに集中できる
- 異なるブラウザやクライアントでも同じように利用できる
- 共通ルールの上で独自の進化が可能
デメリット
- 標準化の代償として、独自最適化や効率の追求がしづらい
つまり!!!
これらのルールを守りながらAPIを設計しましょうというのがREST API。
リクエストを深ぼる
HTTPリクエストの3要素(リクエストの中身)
1. リクエストライン
- サーバーに「何をするか」を伝える部分
- 4つで構成される
-
メソッド
-
GET
: データを読み取りたい(Read) -
POST
: 新しいデータを作りたい(Create)- リソース名が未定のとき(サーバーに「新しく作ってね」とお願いするイメージ)
-
PUT
: データを更新したい/新しく作りたい(Update or Create)- リソース名が決まっているとき(サーバーに「これをこの名前で保存してね」とお願いするイメージ)
-
DELETE
: データを削除したい(Delete) - → この4つは「CRUD(Create, Read, Update, Delete)」に対応している
-
-
リクエストURL
- どのデータを操作するか(住所みたいなもの)
- 例:
/users/1
-
HTTPバージョン
- 通信のルールのバージョン
- 例:
HTTP/1.1
orHTTP/2
-
メソッド
HTTPメソッドとSQLの対応関係
-
GET → SELECT
- データを「読み取る」
- 例: ユーザー一覧を取得
- HTTP:
GET /users
- SQL:
SELECT * FROM users;
- HTTP:
-
POST → INSERT
- 新しいデータを「追加する」
- 例: 新規ユーザーを作成
- HTTP:
POST /users
- SQL:
INSERT INTO users (name, email) VALUES ('rai', 'rai@example.com');
- HTTP:
-
PUT → UPDATE(+INSERTの場合もあり)
- 既存データを「更新する」(なければ新規作成することもある)
- 例: ID=1のユーザーを更新
- HTTP:
PUT /users/1
- SQL:
UPDATE users SET name='rai' WHERE id=1;
- HTTP:
-
DELETE → DELETE
- データを「削除する」
- 例: ID=1のユーザーを削除
- HTTP:
DELETE /users/1
- SQL:
DELETE FROM users WHERE id=1;
- HTTP:
2. ヘッダー
- 「追加の情報(メタデータ)」を伝える部分
-
Content-Type
- サーバーに送るデータの形式を指定
- 例:
application/json
-
User-Agent
- どんなクライアント(ブラウザやアプリ)から送っているか
- 例:
Chrome/120.0
-
Cookie
- サーバーとやり取りするために保持している情報
- Cookieが正体はここに入るヘッダー
-
Content-Type
3. ボディ
- 実際に送りたいデータを入れる部分(任意)
- 主に
POST
やPUT
で使う - 例
JSONデータ
{ "name": “rai”, "email": "rai@example.com" }
レスポンスを深ぼる
HTTPレスポンスの3要素
1. ステータスライン
- 受信に関する基本情報
- 構成:
-
HTTPバージョン
- 例:
HTTP/1.1
- 例:
-
ステータスコード
-
2xx Success
: リクエストが受け入れられて正常処理された -
4xx Client Error
: クライアントのリクエストに誤りがある -
5xx Server Error
: サーバー処理に失敗した
-
-
フレーズ
- ステータスコードを説明する文字列
- 例:
200 OK
,404 Not Found
-
HTTPバージョン
2. レスポンスヘッダー
- ステータスラインだけでは表せない追加情報
- 主な項目:
-
Content-Type
- 応答データのフォーマット
- 例:
application/json
,text/html
-
Cache-Control
- データをキャッシュしてよいかどうか
- 例:
no-cache
,max-age=3600
-
Content-Type
3. レスポンスボディ
- 実際の応答データが入る部分
- 例
JSON形式
{ "id": 1, "name": "rai" }
movieをリソースとしてCRUD操作のURI、HTTPメソッドを定義してみる
URI | HTTP method |
---|---|
GET /movies | GET |
POST /movies | POST |
PUT /movies/{id} | PUT |
DELETE /movies/{id} | DELETE |
さいごに
今回はクライアントサイドからリクエストを送りサーバーサイドから情報をレスポンスするという仕組みの基本を理解することができました。今後、自身が設計する際は上記のことを守りながら行っていこうと思います!