iBetter Books
수정

Ch 02. 환경 변수 관리하기

코드 안에 데이터베이스 비밀번호, API 키, 인증 비밀 키를 직접 써넣으면 어떻게 될까요? GitHub에 코드를 올리는 순간 전 세계에 공개됩니다. 실수로 비밀 키를 커밋한 사고는 생각보다 자주 일어납니다.

환경 변수는 이런 민감한 값들을 코드 밖에서 관리하는 방법입니다.

.env 파일 종류

Next.js는 여러 종류의 .env 파일을 지원합니다.

파일 용도 git 포함
.env 모든 환경의 기본값 가능 (비밀값 없는 경우만)
.env.local 로컬 개발용, 개인 비밀값 절대 금지
.env.development 개발 환경 전용 가능
.env.production 프로덕션 환경 전용 가능
.env.test 테스트 환경 전용 가능

.env.local.gitignore에 반드시 포함되어야 합니다. Next.js 기본 .gitignore에는 이미 포함되어 있습니다.

# .gitignore (이미 포함되어 있음).env*.local```text### NEXT_PUBLIC_ 접두사 — 브라우저 노출 여부환경 변수 접두사에 따라 어디서 접근할 수 있는지 달라집니다.**`NEXT_PUBLIC_` 접두사 있음**: 서버와 브라우저 모두에서 접근 가능합니다. 빌드 시 코드에 인라인됩니다. 즉, 번들을 분석하면 값을 볼 수 있습니다.```typescript// 브라우저에서도 접근 가능const apiUrl = process.env.NEXT_PUBLIC_API_URL;```text**`NEXT_PUBLIC_` 접두사 없음**: 서버에서만 접근 가능합니다. 브라우저 코드에서 `process.env.SECRET_KEY` 읽으면 `undefined`입니다. 데이터베이스 URL, API 비밀 키 같은 민감한 값은 이 방식을 사용합니다.```typescript// 서버 컴포넌트, API 라우트, Server Action에서만 접근 가능const dbUrl = process.env.DATABASE_URL; // 클라이언트에서는 undefinedconst secret = process.env.AUTH_SECRET; // 클라이언트에서는 undefined```text### 로컬 개발 환경 설정```bash# 파일: .env.local# 데이터베이스DATABASE_URL="postgresql://user:password@localhost:5432/myblog"# NextAuthAUTH_SECRET="openssl rand -base64 32로 생성한 값"# Google OAuth (PART 06 참조)AUTH_GOOGLE_ID="your_google_client_id"AUTH_GOOGLE_SECRET="your_google_client_secret"# 공개 가능한 값NEXT_PUBLIC_APP_URL="http://localhost:3000"NEXT_PUBLIC_SITE_NAME="나의 블로그"```text`.env.example` 만들어 팀원과 공유합니다. 실제 값 대신 설명을 적습니다.```bash# 파일: .env.example (git에 포함)DATABASE_URL="postgresql://user:password@host:port/dbname"AUTH_SECRET="openssl rand -base64 32으로 생성"AUTH_GOOGLE_ID="Google Cloud Console에서 발급"AUTH_GOOGLE_SECRET="Google Cloud Console에서 발급"NEXT_PUBLIC_APP_URL="앱 URL"NEXT_PUBLIC_SITE_NAME="사이트 이름"```text### Vercel 대시보드에서 환경변수 설정1. Vercel 프로젝트 → `Settings`  `Environment Variables` 이동합니다.2. 변수명과 값을 입력합니다.3. 적용할 환경을 선택합니다. (Production, Preview, Development)4. `Save` 클릭합니다.5. 새로 배포해야 변경사항이 반영됩니다.Vercel에서는 환경별로 다른 값을 설정할 수 있습니다. 개발 환경(`Preview`)과 프로덕션(`Production`)의 데이터베이스 URL을 다르게 설정하는 것이 좋습니다.### Docker 배포 시 환경변수 주입Docker 컨테이너에서는 `.env.local` 파일이 없습니다. 환경변수를 컨테이너에 주입하는 방법은 두 가지입니다.**방법 1: docker-compose.yml에서 .env 파일 참조**```yaml# 파일: docker-compose.ymlservices:  app:    image: my-blog-app    env_file:      - .env  # 서버의 .env 파일을 읽음 (git에 포함하지 않음)    ports:      - "3000:3000"```text서버에 `.env` 파일을 직접 만들어 관리합니다.**방법 2: docker-compose.yml에 직접 환경변수 선언**```yaml# 파일: docker-compose.ymlservices:  app:    image: my-blog-app    environment:      - DATABASE_URL=${DATABASE_URL}  # 호스트의 환경변수를 전달      - AUTH_SECRET=${AUTH_SECRET}      - NODE_ENV=production    ports:      - "3000:3000"```text### 환경변수 유효성 검사잘못된 환경변수 설정으로 런타임에 에러가 발생하는 것을 방지합니다. `zod` 빌드 시점에 검증합니다.```typescript// 파일: lib/env.tsimport { z } from "zod";const envSchema = z.object({  DATABASE_URL: z.string().url(),  AUTH_SECRET: z.string().min(32),  NODE_ENV: z.enum(["development", "production", "test"]),  NEXT_PUBLIC_APP_URL: z.string().url(),});export const env = envSchema.parse(process.env);

env.ts를 앱 시작 시 import하면 필수 환경변수가 없을 때 명확한 에러 메시지와 함께 실패합니다.

다음 챕터에서는 Docker로 자체 서버에 배포하는 방법을 살펴봅니다.