메인 μ½˜ν…μΈ λ‘œ κ±΄λ„ˆλ›°κΈ°
SonamuλŠ” ν™˜κ²½λ³„λ‘œ λ‹€λ₯Έ 섀정을 μ μš©ν•˜κΈ° μœ„ν•΄ .env νŒŒμΌμ„ μ‚¬μš©ν•©λ‹ˆλ‹€. λ°μ΄ν„°λ² μ΄μŠ€ μ—°κ²° 정보, API ν‚€, μ„Έμ…˜ λΉ„λ°€ν‚€ λ“± λ―Όκ°ν•œ μ •λ³΄λŠ” .env νŒŒμΌμ— μ €μž₯ν•˜κ³  sonamu.config.tsμ—μ„œ μ°Έμ‘°ν•©λ‹ˆλ‹€.
.env νŒŒμΌμ€ μ ˆλŒ€ Git에 μ»€λ°‹ν•˜λ©΄ μ•ˆ λ©λ‹ˆλ‹€! .gitignore에 .envκ°€ ν¬ν•¨λ˜μ–΄ μžˆλŠ”μ§€ ν™•μΈν•˜μ„Έμš”.

λΉ λ₯Έ μ‹œμž‘

.env.example 볡사

ν”„λ‘œμ νŠΈ λ£¨νŠΈμ—μ„œ .env.example을 λ³΅μ‚¬ν•˜μ—¬ .env νŒŒμΌμ„ μƒμ„±ν•©λ‹ˆλ‹€.
cp .env.example .env

ν™˜κ²½λ³€μˆ˜ μ„€μ •

.env νŒŒμΌμ„ μ—΄μ–΄ μ‹€μ œ κ°’μœΌλ‘œ μˆ˜μ •ν•©λ‹ˆλ‹€.
# μ˜ˆμ‹œ
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=your-db-password

μ„€μ • νŒŒμΌμ—μ„œ μ°Έμ‘°

sonamu.config.tsμ—μ„œ process.env둜 ν™˜κ²½λ³€μˆ˜λ₯Ό μ½μŠ΅λ‹ˆλ‹€.
database: {
  defaultOptions: {
    connection: {
      host: process.env.DB_HOST || "0.0.0.0",
      password: process.env.DB_PASSWORD,
    },
  },
}

.env 파일 ꡬ쑰

.env νŒŒμΌμ€ KEY=VALUE ν˜•μ‹μœΌλ‘œ μž‘μ„±ν•©λ‹ˆλ‹€.
# ν”„λ‘œμ νŠΈ μ„€μ •
PROJECT_NAME=MyProject

# λ°μ΄ν„°λ² μ΄μŠ€
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=your-db-password

# μ„Έμ…˜
SESSION_SECRET=your-session-secret  # μ΅œμ†Œ 64자
SESSION_SALT=your-session-salt  # μ΅œμ†Œ 16자

# μŠ€ν† λ¦¬μ§€ (fs λ˜λŠ” s3)
DRIVE_DISK=fs

# AWS S3 (DRIVE_DISK=s3일 λ•Œ)
AWS_ACCESS_KEY_ID=your-aws-access-key-id
AWS_SECRET_ACCESS_KEY=your-aws-secret-access-key
S3_REGION=ap-northeast-2
S3_BUCKET=my-bucket

# μ™ΈλΆ€ API
OPENAI_API_KEY=your-openai-api-key

# μ›Œμ»€
DISABLE_WORKER=false
주석은 #으둜 μ‹œμž‘ν•©λ‹ˆλ‹€. 빈 쀄은 λ¬΄μ‹œλ©λ‹ˆλ‹€.

ν™˜κ²½λ³„ μ„€μ •

.env.development
# 둜컬 개발용 μ„€μ •
PROJECT_NAME=MyProject-Dev

DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=your-dev-password
DATABASE_NAME=myproject_dev

SESSION_SECRET=your-dev-session-secret
SESSION_SALT=your-dev-session-salt

DRIVE_DISK=fs

# 개발용 OpenAI (선택)
OPENAI_API_KEY=sk-***

DISABLE_WORKER=false
νŠΉμ§•:
  • 둜컬 λ°μ΄ν„°λ² μ΄μŠ€ μ‚¬μš©
  • 파일 μ‹œμŠ€ν…œ μŠ€ν† λ¦¬μ§€
  • κ°„λ‹¨ν•œ λΉ„λ°€ν‚€ (λ³΄μ•ˆ λΆˆν•„μš”)

sonamu.config.ts 연동

ν™˜κ²½λ³€μˆ˜λ₯Ό sonamu.config.tsμ—μ„œ μ‚¬μš©ν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€.

κΈ°λ³Έ νŒ¨ν„΄

import { defineConfig } from "sonamu";

export default defineConfig({
  projectName: process.env.PROJECT_NAME ?? "DefaultName",
  
  database: {
    name: process.env.DATABASE_NAME ?? "database_name",
    defaultOptions: {
      connection: {
        host: process.env.DB_HOST || "0.0.0.0",
        port: Number(process.env.DB_PORT) || 5432,
        user: process.env.DB_USER || "postgres",
        password: process.env.DB_PASSWORD,
      },
    },
  },
  
  // ...
});

Nullish Coalescing vs OR

// ꢌμž₯: undefined/null만 λŒ€μ²΄
const name = process.env.PROJECT_NAME ?? "DefaultName";

// undefined, null β†’ "DefaultName"
// ""(빈 λ¬Έμžμ—΄) β†’ "" μœ μ§€
// 0 β†’ 0 μœ μ§€
ν™˜κ²½λ³€μˆ˜κ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μ„ λ•Œλ§Œ 기본값을 μ‚¬μš©ν•˜λ €λ©΄ ??λ₯Ό μ‚¬μš©ν•˜μ„Έμš”. ||λŠ” 빈 λ¬Έμžμ—΄λ„ falsy둜 μ²˜λ¦¬ν•©λ‹ˆλ‹€.

숫자 λ³€ν™˜

// βœ… μ˜¬λ°”λ₯Έ 방법
port: Number(process.env.DB_PORT) || 5432

// ❌ 잘λͺ»λœ 방법
port: process.env.DB_PORT || 5432  // λ¬Έμžμ—΄ "5432"κ°€ 될 수 있음

뢈린 λ³€ν™˜

// βœ… μ˜¬λ°”λ₯Έ 방법
enableWorker: !["true", "1"].includes(process.env.DISABLE_WORKER ?? "false")

// λ˜λŠ”
enableCache: process.env.ENABLE_CACHE === "true"

// ❌ 잘λͺ»λœ 방법
enableCache: process.env.ENABLE_CACHE || false  // "false"도 truthy

λ³΄μ•ˆ λͺ¨λ²” 사둀

κ°•λ ₯ν•œ λΉ„λ°€ν‚€ μƒμ„±ν•˜κΈ°

# 64자 랜덀 λ¬Έμžμ—΄ 생성
openssl rand -base64 48

# λ˜λŠ”
node -e "console.log(require('crypto').randomBytes(48).toString('base64'))"
SESSION_SECRET μ˜ˆμ‹œ:
SESSION_SECRET=your-64-character-random-session-secret-change-in-production
μ΅œμ†Œ 길이:
  • SESSION_SECRET: 64자 이상
  • SESSION_SALT: 16자 이상
  • DB_PASSWORD: 32자 이상 (ν”„λ‘œλ•μ…˜)

.gitignore μ„€μ •

.gitignore
# ν™˜κ²½λ³€μˆ˜
.env
.env.local
.env.*.local

# ν”„λ‘œλ•μ…˜ ν™˜κ²½λ³€μˆ˜λŠ” μ ˆλŒ€ 컀밋 κΈˆμ§€
.env.production

# ν…ŒμŠ€νŠΈμš©λ„ ν—ˆμš©ν•  수 있음 (민감 정보 μ—†λ‹€λ©΄)
# .env.test

.env.example μœ μ§€

.env.example
# μ‹€μ œ κ°’ 없이 ν‚€λ§Œ λ‚˜μ—΄
PROJECT_NAME=

DB_HOST=localhost
DB_PORT=5432
DB_USER=
DB_PASSWORD=

SESSION_SECRET=
SESSION_SALT=
.env.example은 Git에 μ»€λ°‹ν•˜μ—¬ νŒ€μ›λ“€μ΄ μ°Έκ³ ν•˜λ„λ‘ ν•©λ‹ˆλ‹€.

파일 κΆŒν•œ μ„€μ •

# .env 파일 κΆŒν•œμ„ μ†Œμœ μžλ§Œ 읽기/μ“°κΈ°
chmod 600 .env

# 확인
ls -la .env
# -rw------- 1 user user 512 Jan 09 10:00 .env

ν™˜κ²½λ³€μˆ˜ μ ‘κ·Ό μ œν•œ

// βœ… ν•„μš”ν•œ κ³³μ—μ„œλ§Œ μ ‘κ·Ό
const dbPassword = process.env.DB_PASSWORD;

// ❌ λ‘œκ·Έμ— 좜λ ₯ κΈˆμ§€
console.log("Password:", process.env.DB_PASSWORD);

// ❌ ν΄λΌμ΄μ–ΈνŠΈμ— λ…ΈμΆœ κΈˆμ§€
res.send({ secret: process.env.SESSION_SECRET });

GitHub Actions

.github/workflows/deploy.yml
jobs:
  deploy:
    steps:
      - name: Deploy
        env:
          DB_HOST: ${{ secrets.DB_HOST }}
          DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
          SESSION_SECRET: ${{ secrets.SESSION_SECRET }}
        run: |
          npm run deploy

Vercel/Netlify

  1. ν”„λ‘œμ νŠΈ μ„€μ • β†’ Environment Variables
  2. 각 λ³€μˆ˜λ₯Ό κ°œλ³„ μΆ”κ°€
  3. ν™˜κ²½λ³„λ‘œ λ‹€λ₯Έ κ°’ μ„€μ • (Production/Preview/Development)
ν”„λ‘œλ•μ…˜ λΉ„λ°€ν‚€λŠ” μ ˆλŒ€ 개발/μŠ€ν…Œμ΄μ§• ν™˜κ²½μ— μ‚¬μš©ν•˜μ§€ λ§ˆμ„Έμš”!

문제 ν•΄κ²°

증상: process.env.DB_PASSWORDκ°€ undefined원인:
  1. .env 파일이 μ—†μŒ
  2. .env 파일 μœ„μΉ˜κ°€ 잘λͺ»λ¨
  3. λ³€μˆ˜ 이름 μ˜€νƒ€
  4. μ„œλ²„ μž¬μ‹œμž‘ μ•ˆ 함
ν•΄κ²°:
# 1. .env 파일 확인
cat .env | grep DB_PASSWORD

# 2. .env 파일 μœ„μΉ˜ 확인 (ν”„λ‘œμ νŠΈ 루트)
ls -la .env

# 3. μ„œλ²„ μž¬μ‹œμž‘
npm run dev
증상: ν™˜κ²½λ³€μˆ˜ λ³€κ²½ν–ˆλŠ”λ° μ—¬μ „νžˆ 이전 κ°’ μ‚¬μš©μ›μΈ:
  • Node.js ν”„λ‘œμ„ΈμŠ€κ°€ μ‹œμž‘ν•  λ•Œλ§Œ .env νŒŒμΌμ„ 읽음
  • 파일 λ³€κ²½ ν›„ μ„œλ²„ μž¬μ‹œμž‘ ν•„μš”
ν•΄κ²°:
# 개발 μ„œλ²„ μž¬μ‹œμž‘
# Ctrl+C둜 μ’…λ£Œ ν›„
npm run dev
HMR(Hot Module Replacement)은 μ½”λ“œλ§Œ μžλ™ λ¦¬λ‘œλ“œν•˜λ©°, ν™˜κ²½λ³€μˆ˜λŠ” μž¬μ‹œμž‘ν•΄μ•Ό μ μš©λ©λ‹ˆλ‹€.
증상: λ‘œμ»¬μ€ λ˜λŠ”λ° ν”„λ‘œλ•μ…˜μ—μ„œ undefined원인:
  • ν”„λ‘œλ•μ…˜ μ„œλ²„μ— .env 파일이 μ—†μŒ
  • ν˜ΈμŠ€νŒ… ν”Œλž«νΌμ˜ ν™˜κ²½λ³€μˆ˜ μ„€μ • λ―ΈλΉ„
ν•΄κ²°:방법 1: μ„œλ²„μ— .env 파일 배포
# SSH둜 접속 ν›„
cd /path/to/app
nano .env
# λ‚΄μš© λΆ™μ—¬λ„£κΈ° ν›„ μ €μž₯
방법 2: ν˜ΈμŠ€νŒ… ν”Œλž«νΌ ν™˜κ²½λ³€μˆ˜ μ‚¬μš©
  • Vercel: Project Settings β†’ Environment Variables
  • AWS EC2: /etc/environment λ˜λŠ” ~/.bashrc
  • Docker: docker run -e DB_HOST=... -e DB_PASSWORD=...

λ‹€μŒ 단계