JavaScript | Web API:パフォーマンス・セキュリティ - API 利用のベストプラクティス

JavaScript JavaScript
スポンサーリンク

API 利用のベストプラクティスは「安全・高速・壊れない」を同時に満たす設計

API を使うときに初心者がつまずきやすいのは、
「動くコード」と「正しいコード」の違い です。

API は動くだけなら簡単です。
でも、実際のアプリでは

ネットワークが遅い
レスポンスが壊れている
サーバーが落ちている
ユーザーが連打する
攻撃者が変なデータを送る

こういう“現実の世界”が常に起きます。

API 利用のベストプラクティスとは、
「現実の世界でも壊れない API の使い方」 を身につけることです。

ここでは、初心者が最初に押さえるべきポイントを
例題つきで深掘りしていきます。


API の基本原則:失敗を前提に設計する

API は「成功することもあるし、失敗することもある」

API を叩くとき、初心者がやりがちな誤りは
「成功する前提でコードを書く」 ことです。

例えば、こういうコード。

const res = await fetch("/api/user");
const data = await res.json();
console.log(data.name);
JavaScript

一見普通ですが、実際には

レスポンスが 500 エラー
JSON が壊れている
ネットワークが切れた
タイムアウトした

など、いくらでも失敗します。

だから API 利用の基本は
「成功したらこうする、失敗したらこうする」
を必ず書くことです。

正しい書き方の例(成功・失敗を分ける)

async function fetchUser() {
  try {
    const res = await fetch("/api/user");

    if (!res.ok) {
      throw new Error(`サーバーエラー: ${res.status}`);
    }

    const data = await res.json();
    return data;

  } catch (err) {
    console.error("ユーザー情報の取得に失敗:", err);
    return null;
  }
}
JavaScript

ここで重要なのは、

レスポンスが 200 以外ならエラー扱い
JSON パース失敗も catch で拾う
失敗時は null を返して UI 側で分岐

という「壊れない設計」です。


API のパフォーマンス:無駄なリクエストを減らす

同じ API を何度も叩かない

初心者がよくやるミスは、
「必要以上に API を叩く」 ことです。

例えば、スクロールするたびに API を呼ぶ
ボタン連打で API が連続で飛ぶ
画面遷移のたびに同じデータを取得する

こういうのは、
サーバーにもユーザーにも負担です。

対策:キャッシュ・デバウンス・メモ化

例:検索ボックスで入力のたびに API を叩くのは危険です。

悪い例:

input.addEventListener("input", async () => {
  const res = await fetch(`/api/search?q=${input.value}`);
});
JavaScript

良い例(デバウンスで 300ms 以内の連続入力をまとめる):

let timer;

input.addEventListener("input", () => {
  clearTimeout(timer);
  timer = setTimeout(() => {
    fetch(`/api/search?q=${input.value}`);
  }, 300);
});
JavaScript

これで、
「入力のたびに API」→「落ち着いたタイミングで 1 回だけ」
に変わります。


API のセキュリティ:信頼しない・漏らさない・改ざんさせない

API に送るデータは“絶対に信用しない”

ユーザーが入力した値は、
攻撃者が自由に書き換えられる前提で扱います。

例えば、サーバーに送る前に
フロント側でバリデーションしても、
攻撃者は JavaScript を無視して送信できます。

だから API のセキュリティは

フロントでバリデーション(UX のため)
サーバーでバリデーション(安全のため)

の二段構えが基本です。

API キーをフロントに埋め込まない

初心者がやりがちな危険行為:

const API_KEY = "SECRET_ABC123"; // GitHub に上げてしまう
JavaScript

これは 絶対に NG です。

API キーは必ずサーバー側で扱い、
フロントからは触れないようにします。


API のレスポンス設計:UI とセットで考える

API の結果を UI にどう反映するかが重要

API の結果は、
成功・失敗・読み込み中
の 3 状態を UI に反映する必要があります。

例:ユーザー情報を表示する UI

async function showUser() {
  userBox.textContent = "読み込み中…";

  const user = await fetchUser();

  if (!user) {
    userBox.textContent = "取得に失敗しました。再読み込みしてください。";
    return;
  }

  userBox.textContent = `${user.name} さん`;
}
JavaScript

ここで大事なのは、

読み込み中
成功
失敗

の 3 状態を UI で明確に分けていることです。


API の並列処理:Promise.all で高速化する

独立した API は同時に叩く方が速い

悪い例(直列):

const user = await fetch("/api/user");
const posts = await fetch("/api/posts");
JavaScript

良い例(並列):

const [user, posts] = await Promise.all([
  fetch("/api/user"),
  fetch("/api/posts")
]);
JavaScript

これだけで、
待ち時間が半分になることもある ので、
非同期パフォーマンスの基本テクニックです。


API のタイムアウト:永遠に待たない

fetch はデフォルトで“永遠に待つ”

初心者が知らない落とし穴:

await fetch("/api/slow");
JavaScript

これは、
サーバーが応答しない限り永遠に待ち続けます。

対策:AbortController を使う

const controller = new AbortController();

const timeout = setTimeout(() => controller.abort(), 5000);

try {
  const res = await fetch("/api/slow", { signal: controller.signal });
  const data = await res.json();
} catch (err) {
  console.log("タイムアウトしました");
}

clearTimeout(timeout);
JavaScript

これで
「5 秒以内に返ってこなければ諦める」
という設計ができます。


API 利用のベストプラクティスまとめ

API は「動けばいい」ではなく
「失敗しても壊れない」「無駄に叩かない」「安全に扱う」
という視点で設計する必要があります。

成功・失敗・読み込み中の 3 状態を UI に反映する
レスポンスが壊れていても落ちないように try/catch を使う
Promise.all で並列化して高速化する
デバウンスやキャッシュで無駄なリクエストを減らす
API キーは絶対にフロントに置かない
タイムアウトを設けて永遠に待たない
サーバー側でも必ずバリデーションする

あなたが API を書くときに
「この API、失敗したらどうなる?」
「この API、本当に今必要?」
と一度でも考えられるようになったら、
それはもう“API を叩く人”から“API を設計できる人”への第一歩です。

タイトルとURLをコピーしました