본문으로 건너뛰기

ADR 0038 — ops v2 운영 콘솔 정보 아키텍처

날짜: 2026-05-07 상태: Accepted Tier: A (Architecture · 운영 콘솔) 적용 범위: apps/ops 전체 — 사이드바 정보 아키텍처, 시나리오 페이지 routing, 신설 페이지 (운영 가시성·도구·시스템) 의 통합 설계.

결정문

apps/ops 의 평면 메뉴 구조를 5 그룹 정보 아키텍처 (운영·검증·콘텐츠·도구·시스템) 로 재편하고, 시나리오 페이지를 registry-driven subroute 로 마이그레이션하여 운영 효율성·확장성·테스트 안전망을 동시에 확보한다.

배경

apps/ops 는 너홀로프로 운영팀이 production 을 모니터링하고 새 기능을 검증하는 콘솔이다. 2026-04-29 ADR 0028 (비즈니스 로직 추출) 이후 시나리오 카드가 90+ 개로 늘었고, 페이지도 10 개 평면 구조로 성장했다. 다음 한계가 누적되었다.

  1. 평면 사이드바: dashboard / tenants / scenarios / rag-eval / ai-quality / bot-runs / case-prefill / public-rag / public-rag/bulk 가 모두 같은 층에 나열. 영역별 의도 (운영 vs 검증 vs 콘텐츠) 가 사이드바에 안 드러남. 새 페이지 추가할수록 인지부하 증가.
  2. 시나리오 페이지 한 덩어리: scenarios/page.tsx 788줄, import 만 113줄. 카드 등록이 manual list, 단일 페이지라 /scenarios/docs·/scenarios/portal 같은 URL 공유·북마크 불가, 카드 메타 (4 메타 표준, ScenarioCardShell) 가 컴포넌트 내부에 갇혀 검색·필터·자동 회귀 검증에 활용 못 함.
  3. 운영 가시성 0: 2026-05-03 production sweep 에서 functions 메모리 256MiB 부족·ADR 0002 좀비 함수가 gcloud CLI 1회로 발견된 사례. ops 안에 incident timeline·Functions health·Firestore index 누락 detector 가 없어 매주 외부 도구로 우회.
  4. 개발자 마찰 도구 0: 테스트 tenant 1클릭 시드 (e2e/stress 시드는 users/{uid}.consents 까지 chain 메모 반영), feature flags 토글, Cmd+K command palette, debug token 발급 같은 일상적 마찰을 줄이는 도구 부재.
  5. 검증/모니터링 분리 흐림: scenarios (mutation 검증) · rag-eval (RAG 품질) · ai-quality (AI 응답) · bot-runs (자동 e2e) · case-prefill (프리필) 가 한 흐름이지만 평면 메뉴라 의도 안 보이고 신규 운영자가 학습 시 큰 헷갈림.

결정 — 5 그룹 정보 아키텍처

그룹의도페이지
🔭 운영 (Ops)우리가 보는 production 상태dashboard · tenants · incidents ⭐ · health
🧪 검증 (Verify)새 기능 안전망 — production tenant 영향 없이 시뮬레이션scenarios (subroute 화) · case-prefill · bot-runs · rag-eval · ai-quality · journey
📚 콘텐츠 (Content)우리가 채우는 데이터public-rag · public-rag/bulk · legal-news ⭐ · templates
🛠️ 도구 (Tools)마찰 줄이기command-palette (Cmd+K 전역) · tenant-fixture ⭐ · debug-tokens ⭐ · feature-flags
⚙️ 시스템 (System)정책·감사audit-log ⭐ · env ⭐ · members

⭐ = 본 ADR 로 신설. 기존 페이지는 모두 보존하되 그룹만 부여.

시나리오 콘솔 v2 — 핵심 변경

90 카드 단일 페이지 → registry-driven subroute. 4가지 변경:

1. registry 분리 (_lib/scenario-registry.ts)

각 카드별 _components/cards/<domain>/<Card>.tsx 옆에 <Card>.meta.ts 추가. zod 검증된 4 메타 (CLAUDE.md ScenarioCardShell 4 메타 표준 SSoT 와 동일):

// _components/cards/case-lifecycle/CreateCaseScenarioCard.meta.ts
export const meta = scenarioMetaSchema.parse({
key: "create-case",
domain: "case-lifecycle",
title: "사건 생성",
dataModel: "tenants/{tid}/cases/{caseId} ...",
businessLogic: "createCase (packages/business-logic/cases) ...",
meaning: "변호사 사건 등록 진입점. recoveryType·packType ...",
webMapping: "/cases/new → CaseCreateForm ...",
tags: ["mutation", "case", "core"],
});

scripts/build-scenario-registry.ts 가 fs scan → 자동 collect → registry 모듈 생성. 회귀 가드 = apps/ops/__tests__/scenario-registry-coverage.test.ts (모든 cards/**/*ScenarioCard.tsx*.meta.ts 1:1 검증).

2. 도메인 subroute

URL의미
/scenarios인덱스 (도메인 그리드 + 검색 + 즐겨찾기)
/scenarios/[domain]도메인 카드 그리드 (예: /scenarios/case-lifecycle)
/scenarios/[domain]/[card]단독 시나리오 페이지 (URL 공유 가능, PR 리뷰 시 "이 시나리오 한 번 돌려봐" 가 링크로 됨)

기존 scenarios/page.tsx 의 master-detail UX 는 /scenarios 인덱스에서 그대로 유지 — 점진 마이그레이션이라 회귀 위험 최소화.

3. 최근 실행 사이드 패널

모든 시나리오 mutation Server Action 이 tenants/{tid}/opsScenarioRuns/ 에 텔레메트리 append (이미 일부 카드는 진행 중). v2 사이드 패널이 최근 N 건 + 결과 enum + before/after diff 노출. 회귀 의심 시 즉시 재실행.

4. 즐겨찾기·태그 필터·키워드 검색

  • localStorage ops:scenarios:favorites 에 카드 키 저장 → 인덱스 페이지 상단에 "즐겨찾기" 섹션
  • 메타 tags 배열로 필터 (예: mutation · read-only · core · learning · chain)
  • 키워드 검색은 title + meaning + dataModel 토큰 매칭 (Fuse.js 같은 lib 도입 보류 — 단순 substring 으로 충분)

신설 페이지 명세

운영 (Ops)

  • incidents — Cloud Functions 에러 로그 timeline (gcloud Functions API → server fetch, 페이지당 limit 50, 1분 캐시) · Firestore index 누락 detector (collectionGroup 쿼리 실패 catch) · ADR 0029 fail-loud 미준수 신규 코드 검출 (정적 분석) · 5xx 비율
  • health — Functions 메모리·CPU·콜드 스타트·Firestore latency p95 · embed-legacy-doc 실패율 (ADR 0015 학습 루프 건강도)

검증 (Verify)

  • journeye2e/JOURNEY-MATRIX.md 의 19 chain 을 ops 에서 직접 실행 + step-by-step 결과 노출. 기존 scenarios/_components/cards/auto/ChainScenarioCard 확장.

콘텐츠 (Content)

  • legal-news — ADR 0033 일간 법률 뉴스 검증 (현재 시나리오 카드만 있음 → 단독 페이지 승격)
  • templatespublic/docxTemplates/ + tenants/{tid}/docxTemplates/ 공용 템플릿 관리 UI (지금은 Storage 콘솔 사용)

도구 (Tools)

  • command-palette (전역 Cmd+K) — cmdk lib (~5KB), 시나리오·페이지·테스트 tenant 즉시 jump
  • tenant-fixture — "1클릭 시드" 버튼: owner + cases 5건 (Pack 1·2·3·4·5 각 1) + legacyDocuments 10건 + embedding + portal token + users/{uid}.consents chain 한 번에. 매 e2e 작업 시 시드 시간 0.
  • debug-tokens — UUID/portal token 즉시 발급 (지금은 Server Action 직접 호출 우회)
  • feature-flagsconfig/appMetadata.features.* 트리 UI 토글. 지금은 Firestore 콘솔에서 직접 편집 → emulator/production 헷갈림. ops 에 토글 UI + 변경 audit log

시스템 (System)

  • audit-log — masterAdmin 행동 추적 (시나리오 실행·feature flag 변경·tenant fixture 시드)
  • env — 환경변수·secret 상태 (값 마스킹 필수, apps/web/.env.example 가 SSoT)
  • membersmasterAdmins/{email} 화이트리스트 관리 (read-only 시작, write 는 차후 ADR)

위험·완화

위험완화
시나리오 routing 마이그레이션이 기존 e2e 깨뜨림/scenarios 인덱스 페이지를 v1 처럼 master-detail UX 로 유지하며 subroute 점진 추가. 기존 e2e 그대로 통과
90 카드 registry 자동화 시 누락 카드apps/ops/__tests__/scenario-registry-coverage.test.ts 추가 — fs scan 으로 카드 컴포넌트 ↔ registry 1:1 검증
Cloud Functions 로그 fetch 가 production cost 발생ops 에서는 read-only, 페이지당 limit 50, 1분 캐시. fetch 빈도 정량 모니터
Cmd+K palette cmdk lib 도입bundle 크기 ~5KB, ops 만 영향 (web 미영향). MIT 라이선스
ADR 0028 패턴 위반 우려모든 신설 mutation 은 packages/business-logic/<도메인>/ 추출 후 server action thin wrapper

Non-goal

  • web 앱 코드 수정 (의존 규칙 준수)
  • Firestore rules 변경
  • masterAdmin 인증 모델 변경 (masterAdmins/{email} 그대로)
  • 외부 의존성 신규 추가는 cmdk 한 개로 제한

구현 순서 (PR 단위)

PR산출물예상 시간
1본 ADR (doc-only)0:30
2AppSidebar 5 NavGroups + 신설 페이지 placeholder route + e2e1:30
3scenarios registry + meta 파일 batch 생성 (5 도메인)1:30
4scenarios/[domain] subroute + 단독 카드 페이지 + 검색·필터·즐겨찾기1:30
5incidents + health 페이지 v11:30
6Cmd+K palette + tenant-fixture + feature-flags2:00
7audit-log + env + members1:00
8README/문서 갱신 + 자율 세션 메모 + 회귀 마지막 한바퀴0:30

총 약 10시간. 보수 추정 6 PR · 도전 추정 8 PR.

측정 가능한 성공 지표

  • ops 사이드바 클릭 수 group 별 분포 측정 가능 (텔레메트리 후속)
  • 시나리오 단독 페이지 URL 공유 사용률 (PR 본문 링크 포함률)
  • production sweep 빈도 vs 수동 gcloud 시간 (목표: 30초 이하)
  • 매 e2e 작업 시드 준비 시간 (목표: tenant-fixture 후 5초 이하)

후속 과제

  • 시나리오 텔레메트리 (opsScenarioRuns/) 통합 — 일부 카드만 진행 중
  • 시나리오 chain 시각화 (journey 페이지 v2)
  • feature-flags 변경 audit log + 자동 emulator/production 동기화
  • members 화이트리스트 write UI (별도 ADR — 권한 위계 결정 필요)
  • templates 페이지가 docx 미리보기 지원 (별도 ADR — docx-html 변환 결정 필요)

변경 이력

버전날짜변경
1.02026-05-07초안 — ops 운영 콘솔 v2 정보 아키텍처 결정