TS初めてのTypeScript

Day 4非同期とfetchでAPIを叩く

環境変数とAPIキー(秘密はフロントに置かない)

APIキーなどの秘密は環境変数で管理し、ブラウザに露出させない。

APIキーは「秘密」である

多くのAPIは、利用するときにAPIキー(合言葉のような文字列)を必要とします。このキーは、あなたのアカウントで課金される権利そのものです。もし他人に知られると、勝手に使われて高額な請求が来たり、データを盗まれたりします。つまりAPIキーはパスワードと同じ「秘密」で、コードに直接書いたり、外に見える場所に置いたりしてはいけません。

フロントエンドに秘密を置くと全員に見える

ブラウザで動くコード(フロントエンド)は、利用者が中身を自由にのぞけます。開発者ツールを開けば、埋め込まれた文字列はすべて見えます。APIキーをフロントに書くと、サイトを訪れた誰もがそのキーを読み取れてしまいます。

環境変数で秘密をコードの外に出す

秘密の値は、コードに直接書かずに環境変数として渡します。環境変数とは、プログラムの外側(実行環境)に用意しておく設定値のことです。Node.jsでは process.env から読み取ります。実際の値は .env という設定ファイルに書き、そのファイルはGitなどで共有しない(.gitignoreに入れる)のが基本です。

TYPESCRIPT
// .env ファイル(この中身は共有しない)
// API_KEY=sk-xxxxxxxxxxxxxxxx

// サーバー側のコードから読み取る
const apiKey = process.env.API_KEY;

if (!apiKey) {
  // 設定漏れに早く気づけるようにチェックする
  throw new Error("API_KEY が設定されていません");
}
秘密はコードに直書きせず process.env から読む

秘密を使う処理はサーバー側で行う

では、ブラウザからAPIキーが必要なAPIを呼びたいときはどうするか。答えは「ブラウザから直接呼ばない」です。自分のサーバー(Next.jsなら などのサーバー側の入口)にリクエストを送り、そのサーバーの中でAPIキーを使って本物のAPIを呼びます。キーはサーバーの中だけに存在し、ブラウザには渡りません。

ブラウザから直接呼ぶ

TYPESCRIPT
// フロントのコード(ブラウザで動く)
const res = await fetch("https://api.example.com/chat", {
  headers: { Authorization: "Bearer " + apiKey },
});
// apiKey がブラウザに埋め込まれ、誰でも見える

自分のサーバー経由で呼ぶ

TYPESCRIPT
// フロントは自分のサーバーだけを呼ぶ
const res = await fetch("/api/chat", { method: "POST" });
// キーはサーバー側の process.env にあり、ブラウザに出ない

なぜサーバーを経由させるのか

秘密を使う処理を自分のサーバーの中に閉じ込めるためです。ブラウザには「自分のサーバーの入口」だけを見せ、本物のAPIキーはサーバーの環境変数から使う。こうすればキーが利用者に漏れません。AIプロダクトでAIのAPIを使うときも、この形が基本です。

AIにはこう聞く

「このAPIキーを使う処理を、フロントから直接呼ばずにサーバー側(APIルート)に移して、キーは環境変数から読むようにして」と頼むと、安全な構成に直してもらえます。生成後は「キーがフロントのコードに残っていないか」を必ず確認しましょう。

  • APIキーはパスワードと同じ秘密。コードに直書きしない
  • フロントに置くと利用者全員に見えてしまう
  • 秘密は環境変数(process.env)で渡し、.envは共有しない
  • 秘密を使う処理はサーバー側で行い、ブラウザからは自分のサーバー経由で呼ぶ

読んでも腑に落ちない所は、AIに噛み砕いてもらいましょう。

理解度チェック

答えられれば、面接で説明できる状態に一歩近づきます。

Q1

APIキーの扱いとして最も安全なものは?

Q2

フロントエンド(ブラウザで動くコード)にAPIキーを埋め込むと何が問題ですか?

Q3

APIキーをフロントに置かず、環境変数とサーバー経由で扱う理由を説明してください。

記述式です。まず自分の言葉で答えを考えてから、模範解答を開いて自己採点してください。