TL

REST API と fetch(フロントとサーバの通信)

フロントとサーバがデータをやり取りする定番の作法。データを「リソース」と捉え、URL とHTTPメソッドで操作し、結果をJSONで受け取る。それをブラウザから呼ぶのが fetch。

基礎RESTAPIfetchJSON最終更新: 2026-06-04
TL;DR要点だけ先に
  • 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 /usersusers コレクション全体
1件を取得GET /users/42id=42 のユーザー
新規作成POST /usersusers に1件追加
丸ごと更新PUT /users/4242 を置き換え
部分更新PATCH /users/4242 の一部だけ変更
削除DELETE /users/4242 を削除

ポイントは、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 は JS より少しだけ厳格

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. 1回目 … サーバから「応答ヘッダ(ステータス等)」が返るのを待つ。
  2. 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 でも reject しない

fetch は サーバから返事が返ってきた時点で「成功」扱い になります。404500 でも 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(); // 作成されたリソースが返ることが多い
}
ボディの2大ハマりどころ

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、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

RESTAPIfetchJSONRESTAPIfetchJSON
参考: 公式情報