BeaSkyblue

Next.js 読解メモ 05: 外部API・秘匿情報・API Route最小プロキシ

· 3 min read

判断基準(30秒)

  • クライアント直叩きOK
    キー不要 or 完全公開可キー(NEXT_PUBLIC_)、CORS許可、誤用リスク小。
  • 直叩きNG → /api 経由
    秘密キー/Bearerが必要、署名生成が必要、CORSでブロック、レート制御したい。

クライアント直叩きの最小形(公開キーのみ)

"use client";
import { useEffect, useState } from "react";

export default function List() {
  const [data, setData] = useState<any[] | null>(null);
  useEffect(() => {
    const ac = new AbortController();
    fetch(`${process.env.NEXT_PUBLIC_API_BASE}/items`, { signal: ac.signal })
      .then(r => r.json()).then(setData).catch(() => {});
    return () => ac.abort();
  }, []);
  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}

NEXT_PUBLIC_ の値は誰でも見える。秘密は入れない。

最小プロキシ(App Router / Vercel)

// app/api/search/route.ts
export async function GET(req: Request) {
  const { searchParams } = new URL(req.url);
  const q = searchParams.get("q") ?? "";

  const upstream = await fetch(
    `https://third.api.example.com/search?q=${encodeURIComponent(q)}`,
    {
      headers: { Authorization: `Bearer ${process.env.THIRD_API_KEY!}` },
      cache: "no-store", // 上流は毎回取得(状態に応じて調整)
    }
  );

  if (!upstream.ok) {
    return Response.json({ error: "upstream error" }, { status: upstream.status });
  }

  const json = await upstream.json();

  // 共有キャッシュ(CDN)での最適化:1分保持、10分はstaleでも即応→裏で再検証
  return new Response(JSON.stringify(json), {
    headers: {
      "Content-Type": "application/json",
      "Cache-Control": "s-maxage=60, stale-while-revalidate=600",
    },
  });
}
  • クライアントは 同一オリジン/api/search?q=... を叩くだけ → CORS問題も回避
  • 鍵は Vercel の Environment Variables に置き、サーバ側(API Route)だけで読む。

環境変数の鉄則(30秒)

  • 公開NEXT_PUBLIC_XXX(露出OKだけ)
  • 秘密process.env.SECRET(API Route / サーバコンポーネント内のみ)
  • 環境ごとに分離:Production / Preview / Development で別値

よくある落とし穴(30秒)

  • 秘密キーを NEXT_PUBLIC_ に入れる(即流出
  • 外部画像やSDKのCORSで詰まる → /api でプロキシ or 相手側の設定確認
  • レート制限なしで連打 → Upstash等で簡易Rate LimitをAPI Routeに

仕上げチェック(10秒)

  • Bearerキー必須の外部API:/api を挟む
  • CORSでブロック:同一オリジンの /api に逃がす
  • ブログの公開設定:秘密はENV、クライアントには渡さない

以上でこの短期シリーズはおしまいです。必要になったら「画像/フォント最適化」「パフォーマンス計測」「動的ルートの静的化テク」版も用意できます。