본문으로 건너뛰기

Firebase 초기화 헬스체크 운영 가이드 (ADR 0029)

2026-04-29 ops 콘솔 KPI=0 silent failure 사고 후 수립된 fail-loud 정책의 운영 측 가이드. CLAUDE.md "Firebase 초기화 fail-loud" 섹션 + ADR 0029 가 정책 SSoT, 본 문서는 일상 모니터링·복구 절차.

1. 정책 요지

환경변수 미설정 → fallback 빈 객체 export 금지 → 즉시 throw.

  • 금지 패턴:

    • export const adminDb = app ? getFirestore(app) : ({} as ReturnType<typeof getFirestore>) — fallback cast 금지
    • if (!adminDb || typeof (adminDb as { collection?: unknown }).collection !== "function") return; — v9 modular SDK 인스턴스에 .collection 없으므로 항상 가드 통과 못 함
    • silent return / silent skip 가드 일반
  • 권장 패턴:

    • throw new Error("Firebase 미초기화: <env keys>") 즉시 발화 (apps/web/lib/firebase/admin.ts 참고)
    • 무결성 확인이 꼭 필요하면 isFirebaseReady() 단일 SSoT ("app" in instance stable API)

2. 회귀 가드

  • apps/ops/__tests__/firebase-init.test.ts — env 미설정 시 import throw
  • apps/web/__tests__/firebase-init.test.ts — 동일

PR 머지 시 두 테스트 통과 확인. 우회 추가 코드 없음.

3. 일상 모니터링

3.1 매일 06:00 KST (배포 직후)

  • ops 콘솔 dashboard 접속
  • KPI 카드 4종 (테넌트 수·활성 사용자·사건 수·회수 합계) 모두 정상 표시 확인
  • 이상 신호:
    • 모든 카드 0 표시 (테넌트 0건이 아닌 경우) → 즉시 §4 절차
    • 일부 카드만 0 표시 → 도메인별 헬스체크 (§5)

3.2 자동화 모니터링 (TODO — 후속 ship)

  • Cloud Logging: "Firebase 미초기화: NEXT_PUBLIC_FIREBASE_*" 에러 count
  • Sentry alert: 동일 에러 메시지 임계값 → 즉시 알림

현재는 수동 점검 + Firebase Console 로그. 자동화 alert 는 후속 PR 에서.

4. 사고 대응 절차 (KPI 모두 0)

Step 1: 환경변수 검증

# apps/ops 의 NEXT_PUBLIC_FIREBASE_* 환경변수 누락 여부
firebase apphosting:backends:get ops --project <projectId>

또는 App Hosting 콘솔에서 backend 환경변수 확인:

  • NEXT_PUBLIC_FIREBASE_API_KEY
  • NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
  • NEXT_PUBLIC_FIREBASE_PROJECT_ID
  • NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
  • NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
  • NEXT_PUBLIC_FIREBASE_APP_ID

Step 2: 로그 확인

Cloud Logging 에서 ops backend 로그 검색:

  • severity >= ERROR
  • textPayload =~ "Firebase 미초기화"

→ 발화 시점·인스턴스 식별. ADR 0029 정책상 반드시 throw 발화 가 정상.

Step 3: 만약 throw 안 발화하는데 KPI 0 이면 → silent failure 재발

즉시 ADR 0029 정책 위반 점검:

# v9 호환 가드 패턴 grep
grep -rn "typeof.*\.collection.*!== *\"function\"" apps/ops/ apps/web/
grep -rn "{}\\s*as.*\\(Firestore\\|Auth\\|FirebaseApp\\)" apps/ops/ apps/web/

→ 발견 시 isFirebaseReady() 로 교체 PR 즉시 작성. 사고 보고서 ADR cross-link.

Step 4: 복구

  • Step 1 에서 환경변수 누락 → App Hosting 콘솔 또는 apphosting.yaml 에 추가 → redeploy
  • Step 3 에서 v8 호환 가드 발견 → 즉시 PR 작성 → 머지 → redeploy

5. 도메인별 헬스체크

5.1 시나리오 페이지 (ADR 0028)

  • /scenarios 접속 → 임의 도메인 카드 (예: auth/RecordConsentsScenarioCard) 클릭
  • 테스트 tenant 선택 → Run
  • 결과 패널에 성공/실패 + Firestore write 요약 표시 → 정상
  • 0건 표시·에러 메시지 없음 → silent skip 의심 → §4 Step 3

5.2 tenants 페이지

  • /tenants 접속 → 테넌트 목록 표시
  • 0건이지만 actually 테넌트 존재 → silent failure → §4

5.3 public-rag 페이지

  • /public-rag 접속 → publicDocuments count 표시
  • 0건이지만 production 에 데이터 있음 → silent failure → §4

6. 회귀 방지 코드 작성 시 체크리스트

  • Firebase init 진입점에 fallback cast ({} as Firestore) 없는가?
  • env 미설정 시 throw new Error() 발화하는가?
  • 가드 추가 시 (1) fallback 자체를 막는가? (2) 가드 통과 후 호출이 실제 동작하는가 emulator 로 1회 검증?
  • isFirebaseReady() 외 변형 init 검사 만들지 않았나?
  • LLM 코드 hedging 패턴 ("그럴듯한 방어 가드", "환경변수 미설정 시 fallback", "typeof 검사") 없는가?

7. 후속 회의 — UX 두 번째 안전망

ADR 0029 후속 의제: /meeting 빈 상태 vs 실패 상태 UI 패턴 통일 tier=B (2026-05-13 데드라인, P4 디자이너 주도).

  • C-7: 빈/실패 4-state 디자인 시스템
  • C-8: 카피 SSoT
  • C-9: SystemStatusBadge
  • C-10: 에러 토스트 hook

→ 사용자 화면에 "이상하다" 신호 가 도달해야 silent failure 의 두 번째 안전망 완성.

관련 문서