본문으로 건너뛰기

Firebase 에뮬레이터 개발 가이드

로컬에서 production Firestore 를 건드리지 않고 안전하게 개발·검증하는 표준 흐름.

TL;DR

일상 개발 (가벼움 — 권장):

터미널 1: pnpm emulator # auth · firestore · storage · functions
터미널 2: pnpm seed:emulator # 첫 실행 1회
터미널 3: pnpm dev # next dev: web=3000 / ops=3001

브라우저: http://localhost:3000 (web), http://localhost:3001 (ops). Emulator UI: http://localhost:4000.

E2E 테스트 (apphosting 포함 — 무거움):

터미널 1: pnpm emulator:e2e # 위 + apphosting (web=5002 / ops=5003)
터미널 2: pnpm seed:emulator
터미널 3: pnpm e2e # Playwright 가 localhost:5002 향함

E2E 모드의 web/ops 는 firebase 가 spawn 한 next dev 인스턴스 (5002·5003). playwright.config.tsbaseURL: http://localhost:5002 와 정합.


셋업 체크리스트

1. .env.localNEXT_PUBLIC_USE_EMULATOR=true

apps/web/.env.localapps/ops/.env.local 모두 필요:

NEXT_PUBLIC_USE_EMULATOR=true

이 한 줄만 있으면:

  • 클라이언트 SDKconnectFirestoreEmulator 등으로 자동 연결 (apps/web/lib/firebase/client.ts)
  • Admin SDKlib/firebase/admin-emulator.tsFIRESTORE_EMULATOR_HOST · FIREBASE_AUTH_EMULATOR_HOST · FIREBASE_STORAGE_EMULATOR_HOST 자동 셋 (initializeApp 직전)

NEXT_PUBLIC_USE_EMULATORtrue 가 아니면 Server Action 의 모든 mutation 이 production Firestore 직행. 클라만 emulator 보고 서버는 production 쓰는 split-brain 사고 차단을 위해 본 가드가 존재.

서버 콘솔에 다음 로그 떠야 정상:

[Firebase Admin] Emulator 라우팅 활성: Firestore 127.0.0.1:8080 · Auth 127.0.0.1:9099 · Storage 127.0.0.1:9199

2. firebase emulators:start

루트에서 pnpm emulator 실행 — Auth (9099) · Firestore (8080) · Storage (9199) · Functions (5001) 동시 기동. UI 4000.

firebase.jsonemulators 섹션이 SSoT — 포트 변경은 거기서.

3. 시드 — pnpm seed:emulator

emulator 가 떠 있는 동안 1회 실행하면:

  • tenants/t-test-001 (테스트 사무소) — owner 멤버 1명 + super_admin masterAdmin
  • tenants/t-test-001/cases/case-test-001 — 대여금 사건, 회수율 9.4%
  • 변제 1건 + 미래 변론기일 1건
  • config/appMetadata.testing.testTenantIdst-test-001 추가 (ops 시나리오 화이트리스트 자동 통과)

스크립트는 멱등 — 재실행해도 안전.

4. dev 서버 — pnpm dev (또는 individual)

pnpm dev --filter=@neohollo/web # 3000 (or 5002)
pnpm dev --filter=@neohollo/ops # 3001 (or 5003)

ops 시나리오 검증

/scenarios 페이지에서 입력:

  • tenantId: t-test-001
  • caseId: case-test-001

14 개 시나리오 카드 모두 emulator 안전 (운영 데이터 무영향). destructive purgeCase 도 ops 콘솔의 confirm() + isTestTenantId 화이트리스트로 이중 가드.


데이터 보존 (옵션)

pnpm emulator:import 로 띄우면:

  • .firebase/emulator-data 디렉토리에서 자동 복원
  • 종료 시 자동 export — 다음 실행에 시드 + 추가 데이터 유지

pnpm emulator:export 로 수동 스냅샷.


트러블슈팅

포트 점유 매트릭스

두 모드는 상호 배타적. 절대 동시 실행 금지.

포트일상 dev (pnpm emulator + pnpm dev)E2E (pnpm emulator:e2e)
3000web (next dev)
3001ops (next dev)
4000emulator UIemulator UI
5001functions emulatorfunctions emulator
5002web (firebase apphosting → next dev with PORT=5002)
5003ops (firebase apphosting → next dev with PORT=5003)
8080firestore emulatorfirestore emulator
9099auth emulatorauth emulator
9199storage emulatorstorage emulator

흔한 증상

증상원인해결
EADDRINUSE: 3001 (ops 충돌)일상 dev (pnpm dev) 와 E2E (pnpm emulator:e2e) 동시 실행모드 한 번에 하나만. 다른 모드 종료 후 재시작
apphosting emulator 5003 응답 없음ops dev 스크립트의 -p 3001 하드코딩이 PORT 환경변수 무시 (#1123 fix 이전 회귀)apps/ops/package.jsondevnext dev -p ${PORT:-3001} 형식인지 확인
[Firebase Admin] Emulator 라우팅 활성 로그 안 뜸.env.localNEXT_PUBLIC_USE_EMULATOR=true 누락.env.local 확인 후 dev 서버 재시작
seed:emulatorFIRESTORE_EMULATOR_HOST 가 설정되지 않았습니다emulator 가 안 떠 있음다른 터미널에서 pnpm emulator 먼저
ops 시나리오 "테스트 tenant 화이트리스트 외" 거부config/appMetadata.testing.testTenantIds 비어있음pnpm seed:emulator 재실행
좀비 프로세스 (8080 already in use 등)이전 emulator 비정상 종료lsof -ti :8080,:9099,:5001,:5002,:5003 | xargs kill
Google 로그인 'No matching frame'CSP frame-srclocalhost:9099 누락 (#1122 이전 회귀)dev 서버 재시작 (CSP 헤더 갱신)
Rules denied (Firestore 권한 오류)masterAdmins 화이트리스트 누락seed 후 emulator UI 에서 masterAdmins 컬렉션 확인

한 줄 정리 — 좀비 정리 + 재시작

# 모든 emulator/dev 프로세스 강제 종료
lsof -ti :3000,:3001,:4000,:5001,:5002,:5003,:8080,:9099,:9199 | xargs kill -9 2>/dev/null
# 일상 dev 재시작
pnpm emulator & # 백그라운드
pnpm dev

운영 안전선

  • .env.production / 배포 환경에는 NEXT_PUBLIC_USE_EMULATOR=false 또는 미설정. admin-emulator.ts 가 no-op 으로 빠진다.
  • production 자격증명 (FB_ADMIN_*) + emulator 라우팅 동시 는 위험 — emulator 라우팅이 우선이지만 자격증명이 production 인 채로 남는 상태가 헷갈리므로 dev 환경은 dev project (neohollo-dev 등) 자격증명 사용 권장.
  • 시드 스크립트는 emulator 외 절대 실행 금지FIRESTORE_EMULATOR_HOST 가드로 자동 차단되지만, env var 를 수동으로 셋한 후 실수 실행은 가드 우회 가능. 실행 전 1초만 호스트 확인.

관련 문서