How to use environment variables in Next.js

김동현·2026년 3월 4일

next.js 공식문서 번역

목록 보기
23/79

Next.js는 환경 변수를 다루기 위한 기능을 기본적으로 내장하고 있어요. 이를 통해 다음과 같은 일들을 할 수 있답니다.

경고 (Warning): Next.js의 기본 create-next-app 템플릿을 사용하면 모든 .env 파일이 .gitignore에 자동으로 추가됩니다. 이 파일들은 절대로 Git 저장소(Repository)에 커밋(commit)하시면 안 됩니다. 환경 변수에는 비밀번호나 API 키 같은 민감한 정보가 들어있기 때문이죠.


환경 변수 불러오기 (Loading Environment Variables)

Next.js는 .env* 파일들에 적힌 환경 변수들을 process.env로 불러오는 기능을 기본적으로 지원해요.

//filename=".env"
DB_HOST=localhost
DB_USER=myuser
DB_PASS=mypassword

참고 (Note): Next.js는 .env* 파일 안에서 여러 줄(multiline)로 된 변수도 지원한답니다.

# .env

# 이렇게 줄바꿈을 해서 작성할 수도 있고
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
Kh9NV...
...
-----END DSA PRIVATE KEY-----"

# 큰따옴표 안에서 `\n`을 사용해서 한 줄로 작성할 수도 있어요
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nKh9NV...\n-----END DSA PRIVATE KEY-----\n"

참고 (Note): 만약 /src 폴더 구조를 사용하고 계신다면 주의해 주세요! Next.js는 .env 파일들을 /src 폴더 안이 아니라, 반드시 프로젝트의 최상위(부모) 폴더에서만 불러옵니다.

이렇게 .env 파일에 작성해 두면, Node.js 환경에 process.env.DB_HOST, process.env.DB_USER, process.env.DB_PASS가 자동으로 로드되어서 Route Handlers(라우트 핸들러) 등에서 바로 사용할 수 있게 됩니다.

예를 들어볼까요?

//filename="app/api/route.js"
export async function GET() {
  const db = await myDB.connect({
    host: process.env.DB_HOST,
    username: process.env.DB_USER,
    password: process.env.DB_PASS,
  })
  // ...
}

@next/env를 사용해서 환경 변수 불러오기

만약 ORM(예: Prisma 등)의 최상위 설정 파일이나 테스트 러너(Test runner)처럼 Next.js 런타임(실행 환경) 외부에서 환경 변수를 불러와야 할 때가 생길 수 있어요. 그럴 때는 @next/env 패키지를 사용하시면 됩니다.

사실 이 패키지는 Next.js 내부에서도 .env* 파일들을 불러오기 위해 사용하고 있는 도구예요.

사용하려면 먼저 패키지를 설치하고, loadEnvConfig 함수를 사용해 환경 변수를 불러오면 됩니다.

pnpm add @next/env
npm install @next/env
yarn add @next/env
bun add @next/env

설치 후 설정 파일을 작성해 볼까요?

//filename="envConfig.ts" switcher
import { loadEnvConfig } from '@next/env'

const projectDir = process.cwd()
loadEnvConfig(projectDir)
//filename="envConfig.js" switcher
import { loadEnvConfig } from '@next/env'

const projectDir = process.cwd()
loadEnvConfig(projectDir)

이렇게 세팅해 둔 다음, 필요한 곳에서 이 설정을 불러와(import) 사용하시면 됩니다. 예를 들어 ORM 설정 파일에서는 아래처럼 쓸 수 있죠.

//filename="orm.config.ts" switcher
import './envConfig.ts'

export default defineConfig({
  dbCredentials: {
    connectionString: process.env.DATABASE_URL!,
  },
})
//filename="orm.config.js" switcher
import './envConfig.js'

export default defineConfig({
  dbCredentials: {
    connectionString: process.env.DATABASE_URL,
  },
})

다른 변수 참조하기 (Referencing Other Variables)

Next.js는 .env* 파일 안에서 $ 기호를 사용해 다른 변수를 참조하는 것(예: $VARIABLE)을 자동으로 확장(expand)해 줍니다. 이 기능을 활용하면 다른 시크릿 값들을 쉽게 조합할 수 있어요.

예를 들어:

//filename=".env"
TWITTER_USER=nextjs
TWITTER_URL=https://x.com/$TWITTER_USER

위의 예시에서 process.env.TWITTER_URL을 출력해보면 https://x.com/nextjs로 세팅되어 있는 것을 확인할 수 있습니다.

알아두면 좋은 점 (Good to know): 만약 환경 변수의 '실제 값' 자체에 $ 문자를 사용해야 한다면, 이스케이프(escape) 처리를 해주셔야 해요. (예: \$)


브라우저용 환경 변수 번들링 (Bundling Environment Variables for the Browser)

NEXT_PUBLIC_ 이라는 접두사가 붙지 않은 환경 변수들은 오직 Node.js 환경(서버 측)에서만 사용할 수 있습니다. 즉, 브라우저에서는 접근할 수 없다는 뜻이죠. (클라이언트인 브라우저는 서버와 완전히 다른 '환경'에서 실행되기 때문입니다.)

환경 변수의 값을 브라우저에서도 접근할 수 있게 만들려면, Next.js가 빌드 타임(build time)에 클라이언트로 전달되는 자바스크립트 번들 안에 그 값을 "인라인(inline, 직접 삽입)" 하도록 지시해야 합니다. 그러면 코드 상의 process.env.[variable] 참조가 모두 하드 코딩된 실제 값으로 교체됩니다.

이렇게 지시하는 방법은 아주 간단해요. 변수 이름 앞에 NEXT_PUBLIC_을 붙여주기만 하면 됩니다.

//filename=".env"
NEXT_PUBLIC_ANALYTICS_ID=abcdefghijk

이렇게 하면 Next.js는 next build 명령어를 실행할 때, Node.js 환경에 있는 process.env.NEXT_PUBLIC_ANALYTICS_ID에 대한 모든 참조를 실제 환경 변수 값으로 바꿔치기합니다. 덕분에 클라이언트 측 코드 어디에서든 이 값을 사용할 수 있게 되고, 브라우저로 전송되는 자바스크립트 파일 안에 이 값이 직접 삽입됩니다.

참고 (Note): 앱이 한 번 '빌드'되고 나면, 더 이상 이 환경 변수들의 변경사항에 반응하지 않습니다.
예를 들어, 하나의 환경에서 빌드된 결과물을 다른 환경으로 넘기는 Heroku 파이프라인을 사용하거나, 단일 Docker 이미지를 빌드해서 여러 환경에 배포하는 경우를 생각해 보세요. 모든 NEXT_PUBLIC_ 변수들은 빌드될 시점의 값으로 꽁꽁 얼어붙게(frozen) 됩니다. 따라서 프로젝트를 빌드할 때 상황에 맞는 올바른 값이 세팅되어 있어야 합니다. 만약 실행 중(runtime)에 환경 변수 값이 동적으로 바뀌어야 하고 클라이언트가 그 값을 알아야 한다면, 자체적인 API를 만들어서 클라이언트에게 제공해주어야 합니다 (필요할 때마다 요청하거나, 초기화 과정에서 받아오도록 말이죠).

//filename="pages/index.js"
import setupAnalyticsService from '../lib/my-analytics-service'

// 'NEXT_PUBLIC_ANALYTICS_ID'는 'NEXT_PUBLIC_' 접두사가 있으므로 여기서 사용할 수 있어요.
// 이 코드는 빌드 시점에 `setupAnalyticsService('abcdefghijk')` 처럼 변환됩니다.
setupAnalyticsService(process.env.NEXT_PUBLIC_ANALYTICS_ID)

function HomePage() {
  return <h1>Hello World</h1>
}

export default HomePage

주의할 점: 아래처럼 변수를 통해 동적으로 조회(dynamic lookups)하는 경우에는 값이 인라인되지 않습니다!

// 변수를 통해 접근하기 때문에 인라인되지 않습니다! (에러 유발 가능)
const varName = 'NEXT_PUBLIC_ANALYTICS_ID'
setupAnalyticsService(process.env[varName])

// 이 경우도 환경 변수 객체를 변수에 담아 접근하므로 인라인되지 않습니다!
const env = process.env
setupAnalyticsService(env.NEXT_PUBLIC_ANALYTICS_ID)

💡 강사의 팁:
여기서 정말 많은 주니어 개발자분들이 실수를 합니다. 환경 변수를 구조 분해 할당(const { NEXT_PUBLIC_API_KEY } = process.env;)하려고 하거나 변수명으로 동적 접근을 하면 빌드 후에 브라우저에서 undefined가 뜨게 됩니다. 반드시 process.env.NEXT_PUBLIC_변수명 형태로 전체 경로를 하드코딩하듯 명시해 주셔야 번들러가 정확히 인식하고 값을 치환해 줍니다!

런타임 환경 변수 (Runtime Environment Variables)

Next.js는 빌드 타임 환경 변수와 런타임 환경 변수를 모두 지원합니다.

기본적으로 환경 변수는 서버에서만 사용할 수 있습니다. 브라우저에 환경 변수를 노출하려면 반드시 NEXT_PUBLIC_을 접두사로 붙여야 하죠. 하지만 이렇게 노출된 public 환경 변수들은 next build 과정 중에 자바스크립트 번들에 하드코딩(인라인) 되어버립니다.

만약 동적 렌더링(dynamic rendering) 중이라면 서버 측에서 환경 변수를 안전하게 읽어올 수 있습니다.

//ilename="app/page.ts" switcher
import { connection } from 'next/server'

export default async function Component() {
  await connection()
  // cookies, headers 및 기타 Dynamic API들을 사용하면
  // 동적 렌더링(dynamic rendering)으로 전환되며, 
  // 이는 이 환경 변수가 런타임(실행 시점)에 평가된다는 것을 의미합니다.
  const value = process.env.MY_VALUE
  // ...
}
//filename="app/page.js" switcher
import { connection } from 'next/server'

export default async function Component() {
  await connection()
  // cookies, headers 및 기타 Dynamic API들을 사용하면
  // 동적 렌더링(dynamic rendering)으로 전환되며, 
  // 이는 이 환경 변수가 런타임(실행 시점)에 평가된다는 것을 의미합니다.
  const value = process.env.MY_VALUE
  // ...
}

이 방식을 사용하면, 하나의 Docker 이미지를 가지고 서로 다른 환경 변수 값을 주입해가며 여러 환경(개발, 스테이징, 운영 등)에 배포하는 것이 가능해집니다.

알아두면 좋은 점:


테스트 환경 변수 (Test Environment Variables)

development(개발)와 production(운영) 환경 외에도, test(테스트)라는 세 번째 옵션이 있습니다. 개발이나 운영 환경에 기본값을 설정했던 것과 같은 방식으로, 테스트 환경을 위한 .env.test 파일을 만들 수 있어요 (물론 앞의 두 개보다는 자주 쓰이진 않지만요). Next.js는 testing 환경일 때는 .env.development.env.production 파일의 환경 변수를 불러오지 않습니다.

이 기능은 jestcypress 같은 도구로 테스트를 돌릴 때, 오직 테스트 목적으로만 특정 환경 변수를 설정해야 할 경우에 아주 유용합니다. NODE_ENVtest로 설정되어 있으면 테스트 기본값이 로드되는데, 보통 테스트 도구들이 알아서 이 값을 세팅해주기 때문에 여러분이 수동으로 설정할 일은 거의 없습니다.

test 환경은 developmentproduction 환경과 한 가지 작은 차이점이 있으니 꼭 기억해 두세요! .env.local 파일은 로드되지 않습니다. 테스트는 누가 언제 실행하든 항상 동일한 결과를 내야 하기 때문이죠. .env.local은 개발자 개인의 로컬 환경에 맞게 기본값을 덮어쓰기 위해 존재하는 파일인데, 테스트 시에 이 파일이 로드되면 사람마다 테스트 환경이 달라질 수 있잖아요? 그래서 이를 무시하고 모든 테스트 실행이 동일한 환경 변수 기본값을 사용하도록 보장하는 것입니다.

알아두면 좋은 점 (Good to know): 일반적인 기본 환경 변수 파일들과 마찬가지로 .env.test 파일은 Git 저장소에 포함시켜야 하지만, .env.test.local 파일은 .gitignore를 통해 무시되도록 처리해서 저장소에 올리면 안 됩니다.

단위 테스트(Unit test)를 실행하는 동안에도 Next.js가 환경 변수를 불러오는 것과 동일한 방식으로 환경 변수를 세팅하고 싶다면, @next/env 패키지의 loadEnvConfig 함수를 활용하시면 됩니다.

// 아래 코드는 Jest의 global setup 파일이나 
// 이와 유사한 테스트 환경 설정 파일에서 사용할 수 있습니다.
import { loadEnvConfig } from '@next/env'

export default async () => {
  const projectDir = process.cwd()
  loadEnvConfig(projectDir)
}

환경 변수 로딩 순서 (Environment Variable Load Order)

Next.js는 다음 순서대로 환경 변수를 탐색하며, 변수를 찾는 즉시 탐색을 멈춥니다. (이 순서는 면접이나 실무 트러블슈팅에서도 매우 중요해요!)

  1. process.env (이미 운영체제나 실행 환경에 설정되어 있는 변수가 1순위입니다)
  2. .env.$(NODE_ENV).local (예: .env.development.local)
  3. .env.local (단, NODE_ENVtest일 때는 확인하지 않아요.)
  4. .env.$(NODE_ENV) (예: .env.development)
  5. .env

예를 들어볼게요. NODE_ENVdevelopment인 상태에서 동일한 이름의 변수를 .env.development.local.env 두 곳에 모두 정의해두었다면, 우선순위가 더 높은 .env.development.local에 있는 값이 사용됩니다.

알아두면 좋은 점 (Good to know): NODE_ENV에 허용되는 값은 production, development, test 세 가지뿐입니다.


알아두면 좋은 점 (Good to know)

  • 만약 /src 디렉토리(https://nextjs.org/docs/app/api-reference/file-conventions/src-folder)를 사용하고 계시더라도, .env.* 파일들은 반드시 프로젝트의 최상위 루트(root) 폴더에 위치해야 합니다.
  • 환경 변수 NODE_ENV가 따로 할당되지 않은 경우, Next.js는 next dev 명령어를 실행할 때 자동으로 development를 할당하고, 그 외의 모든 명령어에서는 production을 할당합니다.

버전 변경 기록 (Version History)

버전 (Version)변경 사항 (Changes)
v9.4.0.envNEXT_PUBLIC_ 지원이 도입되었습니다.

모든 문서의 의미론적 개요(semantic overview)를 보시려면 https://nextjs.org/docs/sitemap.md를 참고해 주세요.

사용 가능한 모든 문서의 색인(index)을 보시려면 https://nextjs.org/docs/llms.txt를 참고해 주세요.

profile
프론트에_가까운_풀스택_개발자

0개의 댓글