REST API と fetch(フロントとサーバの通信)
フロントとサーバがデータをやり取りする定番の作法。データを「リソース」と捉え、URL とHTTPメソッドで操作し、結果をJSONで受け取る。それをブラウザから呼ぶのが fetch。
- 1.REST は データを「リソース」とみなし、URL で場所を、HTTPメソッド(GET/POST…)で操作を表す API の設計スタイル。
- 2.やり取りの中身はたいてい JSON。「どうなったか」はステータスコード(200/404/500…)で判断する。
- 3.ブラウザからは fetch(+ async/await)で呼ぶ。ネットワークエラーと「HTTPエラー」は別物なので、res.ok の確認を忘れない。
REST 自体は厳密な仕様ではなく設計スタイル(流儀)です。だから「これは100%RESTだ/違う」と白黒つけにくく、実務では「RESTっぽい(RESTful な)HTTP API」を指して REST API と呼ぶことがほとんどです。土台は HTTP なので、HTTP のメソッドとステータスコードが分かっていれば話の半分は終わっています。
RESTの考え方(リソースとURI)
REST の中心にあるのは「操作ではなく“もの”に名前をつける」発想です。
- リソース = 扱う対象(ユーザー、記事、注文…)。それぞれに URI(URL) という住所を与える。
- 「何をするか」は URL に書かない。動詞は HTTPメソッド が担当する。
たとえば「ユーザー」というリソースなら、こう整理できます。
| やりたいこと | メソッド + URL | 意味 |
|---|---|---|
| 一覧を取得 | GET /users | users コレクション全体 |
| 1件を取得 | GET /users/42 | id=42 のユーザー |
| 新規作成 | POST /users | users に1件追加 |
| 丸ごと更新 | PUT /users/42 | 42 を置き換え |
| 部分更新 | PATCH /users/42 | 42 の一部だけ変更 |
| 削除 | DELETE /users/42 | 42 を削除 |
ポイントは、URL には「名詞(リソース)」を、操作は「メソッド(動詞)」を使うこと。/getUser?id=42 や /deleteUser のように URL に動詞を入れるのは REST の流儀からは外れます(動いてしまうので“悪”ではないですが、設計としては惜しい)。
URL は「コレクション(複数形)/ 要素(id)」の2段で考えると迷いません。/users は集合、/users/42 はその中の1人。さらに「42 の注文一覧」なら /users/42/orders のように入れ子で表します。
JSON(やり取りの共通フォーマット)
REST API がやり取りするデータの中身は、いまや圧倒的に JSON(JavaScript Object Notation) です。人にも読みやすく、ほぼすべての言語で扱えます。
{
"id": 42,
"name": "Taro",
"tags": ["web", "frontend"],
"active": true
}
JSON は「文字列」です。一方、JavaScript で扱いたいのは「オブジェクト」。この変換を意識するのが第一歩です。
JSON.parse(文字列)… JSON文字列 → JSオブジェクト(受け取るとき)JSON.stringify(オブジェクト)… JSオブジェクト → JSON文字列(送るとき)
fetch では res.json() がこの parse を内部でやってくれるので、自分で JSON.parse を書く場面はそれほど多くありません。送信側で JSON.stringify を使う頻度の方が高いです。
JSON ではキーも必ず ダブルクォート で囲み、末尾カンマ禁止、コメントも書けません。{name: "Taro",} のような“JSっぽい”書き方は JSON としては不正です。手書きで詰まったら構文をまず疑いましょう。
fetch でデータを取得する
ブラウザ標準の fetch で、先ほどの窓口を叩きます。fetch は Promise を返すので、async/await で書くとほぼ同期コードのように読めます。
async function getUser(id) {
const res = await fetch(`/users/${id}`); // 既定は GET
const user = await res.json(); // 本文(JSON)を取り出す
return user;
}
ここで await が2回出てくるのが要点です。
- 1回目 … サーバから「応答ヘッダ(ステータス等)」が返るのを待つ。
- 2回目 …
res.json()で「本文」を最後まで読み、JSオブジェクトに変換するのを待つ。
ステータスコードと「成功/失敗」
サーバが「どうなったか」は ステータスコード で返ってきます(詳しくは HTTP 参照)。fetch では res.status(数値)や res.ok(200〜299 なら true)で確認します。
- 2xx 成功:
200 OK/201 Created(作成成功)/204 No Content(成功・本文なし) - 4xx こちらのミス:
400 不正/401 未認証/403 権限なし/404 なし - 5xx サーバ側の障害:
500 内部エラー/503 利用不可
fetch は サーバから返事が返ってきた時点で「成功」扱い になります。404 や 500 でも await fetch(...) は例外を投げません。catch に入るのは「サーバに届かなかった」場合(回線断・DNS失敗・CORS拒否など)だけ。だから res.ok の確認は必須です。これを忘れると、エラーJSONを正常データと勘違いして画面が壊れます。
「ネットワークエラー」と「HTTPエラー」は別物、と整理すると分かりやすいです。
| 状況 | fetch の挙動 | 見分け方 |
|---|---|---|
| 404 / 500 が返った | 解決(resolve)する=成功扱い | res.ok が false |
| 回線断・DNS失敗・CORS拒否 | 却下(reject)=catch に入る | そもそも res が無い |
エラー処理込みの取得(実用形)
res.ok の確認と try/catch を組み合わせた、実務で使える形がこちらです。
async function getUser(id) {
try {
const res = await fetch(`/users/${id}`);
if (!res.ok) {
// 404/500 など HTTP エラーは自分で投げて catch に流す
throw new Error(`HTTP ${res.status}`);
}
return await res.json();
} catch (err) {
// 回線断・CORS・上で投げた HTTP エラーが、ここに集約される
console.error('取得に失敗:', err);
throw err; // 呼び出し側で握りつぶさないよう再送出
}
}
データを送る(POST / PUT)
新規作成や更新では、メソッド・ヘッダ・ボディを指定します。ボディは JSON.stringify で文字列化し、Content-Type で「これは JSON です」とサーバに伝えるのが定石です。
async function createUser(data) {
const res = await fetch('/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data), // オブジェクト → JSON文字列
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json(); // 作成されたリソースが返ることが多い
}
1つめ:body に生のオブジェクトを渡すと意図通りに送れません。必ず JSON.stringify で文字列にします。
2つめ:Content-Type の付け忘れ。これが無いとサーバが本文を JSON として解釈できず、400 で弾かれがちです。
つまずきポイントまとめ
res.okを見ない … 404/500 がcatchに入ると思い込むと事故ります(最頻出)。res.json()の二重消費 … レスポンス本文は一度しか読めません。res.json()を2回呼ぶとエラーになります。- 本文が空なのに
res.json()…204 No Contentのときにjson()すると失敗します。ステータスで分岐を。 - 別ドメインを叩いて怒られる … ブラウザの安全機構によりブロックされることがあります。これは CORS の話で、サーバ側の許可設定が必要です。
- メソッドが GET 固定だと思っている … fetch の既定は GET。送信・更新では
methodの指定を忘れずに。
fetch の中身そのもの(メソッド・ステータス・ヘッダ)は HTTP / HTTPS を読むと一段深まります。別ドメインのAPIを叩いて弾かれたら CORS、ログイン付きAPIを扱うなら Web 認証 へ。
Web/フロントエンド Article
REST API と fetch(フロントとサーバの通信)を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
REST
比較で見る軸
難易度: basic / カテゴリ: Web/フロントエンド / タグ数: 4
導入後に効く点
やり取りの中身はたいてい JSON。「どうなったか」はステータスコード(200/404/500…)で判断する。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- basic
- カテゴリ
- Web/フロントエンド
- タグ数
- 4
判断チェックリスト
- 自社の用途が「REST / API」に近いか確認する。
- 強みである「REST は データを「リソース」とみなし、URL で場所を、HTTPメソッド(GET/POST…)で操作を表す API の設計スタイル。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。