Next.js NEXT_PUBLIC_環境変数の完全ガイド:安全な使い方とセキュリティリスクの回避

Next.jsアプリケーション開発において、クライアントサイドで環境変数を使用する際に欠かせないNEXT_PUBLIC_プレフィックスについて、その仕組みから正しい使用法、そして重要なセキュリティリスクまで詳しく解説します。

目次

NEXT_PUBLIC_とは?

NEXT_PUBLIC_は、Next.jsで使用する特別なプレフィックス(接頭辞)です。環境変数の名前の前にこのプレフィックスを付けることで、その環境変数をサーバーサイドだけでなく、ブラウザ側(クライアントサイド)でも使用できるようになります。

基本的な仕組み

通常、Next.jsの環境変数はサーバーサイドでのみアクセス可能ですが、NEXT_PUBLIC_プレフィックスが付いた環境変数は、ビルド時にクライアントサイドのJavaScriptバンドルに自動的に組み込まれます。

// .env.local
NEXT_PUBLIC_API_URL=https://api.example.com
SECRET_API_KEY=your-secret-key

// クライアントサイドのコンポーネント
export default function MyComponent() {
  const apiUrl = process.env.NEXT_PUBLIC_API_URL; // ✅ 利用可能
  const secretKey = process.env.SECRET_API_KEY; // ❌ undefined
  
  return <div>API URL: {apiUrl}</div>;
}

なぜNEXT_PUBLIC_が必要なのか?

Next.jsアプリケーションを開発する際、以下のような状況でクライアントサイドでも環境変数を使用したいケースがあります:

  1. ウェブサイトの基本設定(サイト名、説明文、連絡先など)
  2. 公開APIのベースURL(外部サービスの公開エンドポイント)
  3. 機能の切り替えフラグ(フィーチャーフラグ、A/Bテストなど)
  4. 分析ツールの設定(Google Analytics ID、Mixpanel IDなど)
  5. 地図サービスの公開トークン(Mapbox、Google Maps APIの公開キー)

これらの情報は公開されても問題がないため、クライアントサイドでも使用できると開発が効率的になります。

NEXT_PUBLIC_と通常の環境変数の違い

環境通常の環境変数NEXT_PUBLIC_環境変数
サーバーサイド✅ アクセス可能✅ アクセス可能
クライアントサイド❌ アクセス不可✅ アクセス可能
セキュリティ🔒 非公開⚠️ 公開される

NEXT_PUBLIC_の使い方

1. 環境変数の設定

プロジェクトのルートディレクトリに.env.localファイルを作成し、環境変数を記述します。

# 安全な公開情報
NEXT_PUBLIC_SITE_TITLE=My Awesome Blog
NEXT_PUBLIC_API_URL=https://api.myapp.com
NEXT_PUBLIC_ENABLE_NEW_FEATURE=true
NEXT_PUBLIC_GOOGLE_ANALYTICS_ID=GA-XXXXXXXXX

# 機密情報(NEXT_PUBLIC_は付けない)
DATABASE_URL=postgresql://localhost:5432/mydb
SECRET_API_KEY=your-secret-key-here

2. コード内での使用

設定した環境変数は、process.env.NEXT_PUBLIC_変数名の形式でアクセスできます。

// pages/index.js
import Head from 'next/head';

export default function Home() {
  const siteTitle = process.env.NEXT_PUBLIC_SITE_TITLE;
  const apiUrl = process.env.NEXT_PUBLIC_API_URL;
  const enableNewFeature = process.env.NEXT_PUBLIC_ENABLE_NEW_FEATURE === 'true';

  return (
    <div>
      <Head>
        <title>{siteTitle}</title>
      </Head>
      
      <h1>{siteTitle}</h1>
      
      {enableNewFeature && (
        <div>新機能が有効です!</div>
      )}
      
      <button onClick={() => fetchData()}>
        データを取得
      </button>
    </div>
  );

  async function fetchData() {
    const response = await fetch(`${apiUrl}/users`);
    const data = await response.json();
    console.log(data);
  }
}

⚠️ 重要なセキュリティリスクと注意点

1. 機密情報の漏洩リスク

最も重要な注意点: NEXT_PUBLIC_プレフィックスの付いた環境変数は、ビルド時にクライアントサイドのJavaScriptバンドルに平文で埋め込まれます。つまり、ブラウザの開発者ツールやソースコードから誰でも確認できる状態になります。

// 危険な例 - 絶対にやってはいけません
NEXT_PUBLIC_API_SECRET_KEY=abc123456789  // ❌ 機密情報が漏洩
NEXT_PUBLIC_DATABASE_PASSWORD=mypassword  // ❌ パスワードが公開
NEXT_PUBLIC_JWT_SECRET=secret_token  // ❌ 認証情報が露出
NEXT_PUBLIC_STRIPE_SECRET_KEY=sk_live_...  // ❌ 決済情報が危険

2. 悪用される可能性

漏洩した機密情報は以下のような悪用につながる可能性があります:

  • 不正なAPIアクセス
  • データベースへの不正侵入
  • 金銭的な損失(決済サービスの悪用)
  • 個人情報の流出

正しい使用法とベストプラクティス

安全な使用例

// 公開しても問題ない情報のみ
NEXT_PUBLIC_SITE_NAME=My Portfolio
NEXT_PUBLIC_SITE_URL=https://myportfolio.com
NEXT_PUBLIC_CONTACT_EMAIL=hello@myportfolio.com
NEXT_PUBLIC_GOOGLE_ANALYTICS_ID=GA-XXXXXXXXX
NEXT_PUBLIC_MAPBOX_PUBLIC_TOKEN=pk.eyJ1IjoiZXhhbXBsZSI...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...  // 公開キーのみ

機密情報の適切な扱い方

機密情報はサーバーサイドでのみ使用し、API Routesを通じてクライアントに必要な情報のみを提供します。

// pages/api/users.js(サーバーサイド)
export default async function handler(req, res) {
  // 機密情報はサーバーサイドでのみ使用
  const apiKey = process.env.SECRET_API_KEY;
  const dbUrl = process.env.DATABASE_URL;
  
  try {
    const response = await fetch('https://api.example.com/users', {
      headers: {
        'Authorization': `Bearer ${apiKey}`
      }
    });
    const data = await response.json();
    
    // 必要な情報のみをクライアントに返す
    res.json({ users: data.users });
  } catch (error) {
    res.status(500).json({ error: 'Internal Server Error' });
  }
}
// pages/index.js(クライアントサイド)
export default function Home() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    // サーバーサイドのAPIを呼び出し
    fetch('/api/users')
      .then(res => res.json())
      .then(data => setUsers(data.users));
  }, []);

  return (
    <div>
      {users.map(user => (
        <div key={user.id}>{user.name}</div>
      ))}
    </div>
  );
}

TypeScriptでの型安全性の確保

TypeScriptを使用している場合は、環境変数の型を宣言することで、より安全に使用できます。

// types/env.d.ts
declare namespace NodeJS {
  interface ProcessEnv {
    // 公開環境変数
    NEXT_PUBLIC_SITE_TITLE: string;
    NEXT_PUBLIC_API_URL: string;
    NEXT_PUBLIC_ENABLE_NEW_FEATURE: string;
    
    // 機密環境変数(サーバーサイドのみ)
    DATABASE_URL: string;
    SECRET_API_KEY: string;
  }
}

環境別の設定管理

開発環境と本番環境で異なる値を使用したい場合は、複数の環境ファイルを使い分けることができます。

# .env.development(開発環境)
NEXT_PUBLIC_API_URL=http://localhost:3001
NEXT_PUBLIC_ENABLE_DEBUG=true

# .env.production(本番環境)
NEXT_PUBLIC_API_URL=https://api.myapp.com
NEXT_PUBLIC_ENABLE_DEBUG=false

チェックリスト:安全な使用のために

使用前に以下の点を必ず確認してください:

  • [ ] その情報が公開されても問題ないか?
  • [ ] APIキー、パスワード、トークンなどの機密情報が含まれていないか?
  • [ ] 公開トークンを使用する場合、必要最小限の権限のみが付与されているか?
  • [ ] 環境別(開発・本番)で適切に値が設定されているか?
  • [ ] チームメンバーがセキュリティリスクを理解しているか?

まとめ

NEXT_PUBLIC_プレフィックスは、Next.jsでクライアントサイドの環境変数を扱う便利な機能ですが、セキュリティリスクを理解して適切に使用することが重要です。公開されても問題ない情報のみに使用し、機密情報は必ずサーバーサイドで管理するようにしましょう。

正しく理解して使用することで、セキュリティを保ちながら効率的なNext.jsアプリケーション開発が可能になります。

この記事を書いた人

目次