🐙

安全に環境変数を扱うならこれ!@t3-oss/env-nextjs の使い方と導入メリット

に公開1

あなたは今までに環境変数をタイポした回数を覚えていますか?

Next.js で環境変数を使うとき、こんな経験はありませんか?

  • .env.local にミスがあっても気づかず、デプロイ後にエラー
  • クライアントとサーバーのスコープが曖昧で混乱
  • 「あれ、この変数って NEXT_PUBLIC_ つけるんだっけ?」

そんな悩みを一気に解決してくれるのが、T3 Stack で使われている @t3-oss/env-nextjs です。
このライブラリを使えば、環境変数を型安全に、かつ安心して管理することができます

本記事では、@t3-oss/env-nextjs の導入手順から実践的な使い方、よくある落とし穴とその対処法までを丁寧に解説します。


なぜ @t3-oss/env-nextjs が必要か?

Next.js では process.env を直接使って環境変数にアクセスできます。しかし、以下のような課題があります。

課題 問題点
型がない 変数名の typo や型ミスに気づけない
バリデーションできない 値が空でも気づかない
クライアント/サーバーの混在 セキュリティリスクや混乱の元
環境ごとの管理が難しい .env が肥大化しがち

これらを解決するために、T3 Stack の開発者たちが設計したのが @t3-oss/env-nextjs です。


特徴とメリット

  • Zod によるバリデーション
  • サーバー用 / クライアント用 に明確に分離
  • 型補完が効くので開発効率もアップ
  • NEXT_PUBLIC_ の強制でセキュリティ担保
  • ✅ App Router / TypeScript 環境でも安心して使える

インストール

npm install @t3-oss/env-nextjs zod

基本の使い方

まずは env.mjs(または env.ts)ファイルをプロジェクトのルートに作成します。

env.mjs

import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";

export const env = createEnv({
  server: {
    DATABASE_URL: z.string().url(),
  },
  client: {
    NEXT_PUBLIC_API_URL: z.string().url(),
  },
  runtimeEnv: {
    DATABASE_URL: process.env.DATABASE_URL,
    NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
  },
});

🔒 クライアントで使う変数は必ず NEXT_PUBLIC_ で始める必要があります。これがセキュリティの第一歩!


.env.local に定義

DATABASE_URL=https://db.example.com
NEXT_PUBLIC_API_URL=https://api.example.com

.env.local.gitignore に含めておきましょう。共有には .env.example を用意するのがベストプラクティスです。


使用例

✅ サーバーサイド

import { env } from "@/env";

export async function fetchData() {
  const res = await fetch(`${env.DATABASE_URL}/data`);
  return res.json();
}

✅ クライアントサイド

"use client";

import { env } from "@/env";

export default function Page() {
  return <div>API: {env.NEXT_PUBLIC_API_URL}</div>;
}

よくあるエラーと対処法

runtimeEnv is missing

createEnvruntimeEnvprocess.env.XYZ を忘れていませんか?

ZodError: Invalid URL

.env.local の値が z.string().url() に合っていない可能性があります。

❌ クライアントから DATABASE_URL を参照している

→ サーバー専用変数をクライアントで使うとビルドエラーになります(これは 意図的なガード です)


ベストプラクティスまとめ

項目 内容
変数の命名 クライアントで使うものは NEXT_PUBLIC_
型の定義 z.string(), z.number(), z.enum([...]) など
ファイル配置 env.ts or env.mjs/src に置くのが一般的
テスト環境 .env.test を活用し、テスト用に別定義するのも有効

おわりに

@t3-oss/env-nextjs は一見地味ですが、堅牢でセキュアな開発を支える最重要ライブラリのひとつです。
とくに App Router + TypeScript 環境において、「何がクライアントに漏れてよくて、何がダメなのか」を明確にしてくれる点はとても大きな価値があります。

ぜひあなたの Next.js プロジェクトにも導入して、環境変数の管理を「型安全・セキュア・安心」なものにしていきましょう!


参考リンク


✍️ 使用した感想

T3 Stack の思想はかなりとんがっていますが @t3-oss/env-nextjs は部分的に「型安全さ」を取り入れる事ができてなかなか良いなあ、と思いました。おしまい。

Discussion

okamuuuokamuuu

なお、この記事の99%はAIが書いています。もし、間違いがあったらごめんなさい。