Files
llm-wiki/raw/branch-notes/feature-frontend-env-runtime-config-contract.md
T
DongHyeonka d6dfda64ab docs(branch): 기존 7개 노트를 개정 결정·신규 위임에 정합
- REGISTRY-001 Summary 문자열 4곳 (additive, revision 은 1 유지).
  registry-governance 는 본문 서술 12곳의 '8개'도 함께 9개로 갱신
- OFFLINE-CACHE-001 pin @1->@2 와 Summary·적용점 (behavior-change)
- DELEG-FE-007~011 delegate 5곳 접수 완료 — 미접수 위임 0건
- runtime-schema-validation 이 FLOW-FE-EVENT-003/004 소유를 명시
- env-runtime-config 가 FE-REG-CAPABILITY registry 와 FE-GATE-033 gate
  owner 를 취득하고 claim 2건 추가
- 신규 6개 노트의 delegation pin 을 기존 @1 형식으로 정규화
2026-07-28 14:40:38 +09:00

43 KiB
Raw Blame History

title, source_type, status, id, kind, project, work_item, inherits, refines, overrides, depends_on, contract_packet, branch, parent_branch, related_projects, governing_docs, tags, created, target_merge, status_label, contract_packet_sha256, imports
title source_type status id kind project work_item inherits refines overrides depends_on contract_packet branch parent_branch related_projects governing_docs tags created target_merge status_label contract_packet_sha256 imports
branch / feature-frontend-env-runtime-config-contract branch-note raw BR-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-004 project-work-item ca-skeleton-frontend-operational-contract WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-004
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-RUNTIME-CONFIG-001@1
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CONFIG-FALLBACK-001@1
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CAPABILITY-001@1
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-001
1 feature-frontend-env-runtime-config-contract
ca-skeleton-frontend
ca-skeleton
raw/project-notes/ca-skeleton-frontend-operational-contract.md
branch
ca-skeleton
frontend
runtime
security
javascript
externalized-config
2026-07-18 in-progress 781ef2d614370c6a8603dfd4c254c8584737803fa6f88b19159cb46a349e841c
FE-GATE-004@1
FE-GATE-033@1
FE-OC-002@1
FE-OC-003@1
FE-OC-007@1
FE-OC-008@1
FE-OC-009@1
FE-OC-014@1
FE-OC-016@1
FE-OC-019@1
FE-OC-022@1
FE-OC-023@1
FE-OC-025@1

branch: feature-frontend-env-runtime-config-contract

Layer: raw/branch-notes/ — 단일 브랜치의 TODO·결정·진행 기록. 머지/종료 후 verified 결과는 /ingestwiki/projects/에 추출한다.

부모 (필수)

브랜치 계약 패킷

  • 생성 시 프로젝트 개정: 1
  • 패킷 스키마: contract_packet: 1
  • 완료 조건: build/runtime/secret registry와 boot-invalid matrix가 검증된다

상속한 프로젝트 결정

Decision Ref Project Summary Branch Application Source
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-RUNTIME-CONFIG-001@1 deploy별 public value는 runtime config, compiler value는 build-time config로 분리한다 config registry와 pre-mount runtime config validation에 적용한다 raw/project-notes/ca-skeleton-frontend-operational-contract
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CONFIG-FALLBACK-001@1 runtime config fallback 시 environment별 rebuild는 허용하되 artifact의 multi-environment 재사용은 금지한다 static-only hosting fallback과 artifact 재사용 금지에 적용한다 raw/project-notes/ca-skeleton-frontend-operational-contract
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CAPABILITY-001@1 신규 runtime capability 6종은 FE-REG-CAPABILITY flag로 default OFF이며 활성화는 owner·gate·runbook을 동반한다 FE-REG-CAPABILITY(hub §5.11) registry owner 로서 capability flag 6개의 schema·기본값·검증을 소유하고 FE-GATE-033 을 집행한다 raw/project-notes/ca-skeleton-frontend-operational-contract

브랜치 지역 결정

Decision ID Decision Relation Supporting Claims Status
D1 build-time public·runtime-public·secret config를 분리한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D2 runtime config fallback은 environment별 rebuild만 허용한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D3 secret-name key를 build·runtime registry에서 거부한다 local raw/official-docs/vite-build-tool-official.md#VITE-C4, raw/official-docs/vite-build-tool-official.md#VITE-C5 proposed
D4 React mount 전에 runtime config를 fetch하고 검증한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D5 runtime config validation matrix를 고정한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D6 boot failure 화면은 safe field만 노출한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D7 모든 public config는 FE-REG-ENV를 경유한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D8 boot config validation 시간 예산의 측정 구간을 고정한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed

선언한 예외

Override ID Overrides Reason Approval Status

없음.

목표

이 브랜치는 project-wide 계약 FE-OC-004("build-time / runtime-public / secret config를 MUST 분리하고 boot 전에 runtime config를 검증")를 되묻지 않고 코드를 작성할 수 있는 구현 명세로 내린다. 구체적으로 (1) 환경 config registry FE-REG-ENV(src/contracts/env.js)를 single owner로 소유하고, (2) React mount 이전에 실행되는 runtime config fetch·검증 게이트(boot sequence 2~4단계, hub §4.5/§6.3)를 정의하며, (3) 세 종류 config(build-time public / runtime public / secret)의 분리 규칙과 secret 유출 차단 규칙(hub §6.1)을 확정한다. 근거는 hub decision FE-D012(deploy별 public value = pre-render runtime config, compiler value = build-time config)·FE-D013(runtime config fallback 규칙)과 Vite 공식 문서의 import.meta.env build-time 정적 치환·VITE_ prefix 노출 경계·secret 금지 경고(VITE-C3/VITE-C4/VITE-C5)다. 이 계약은 FE-OC-016(release/cache — runtime config cache policy)과 FE-OC-023(compatibility — config/API schema version)에 기여한다. 현재 frontend repository는 존재하지 않으므로 본 노트의 모든 구현 항목 등급은 planned다.

  • 이슈: (없음 — repository 미생성)
  • PR: (없음 — repository 미생성)

범위

포함 범위

  • FE-REG-ENV 환경 config registry(src/contracts/env.js)의 schema·초기 row·single-owner 규칙 (FE-OC-004, hub §5.4)
  • build-time public / runtime public / secret 3분류 규칙과 VITE_ prefix 사용 경계 (FE-D012, hub §6.1)
  • secret-name(SECRET/PASSWORD/PRIVATE_KEY/TOKEN) key를 build·runtime registry 양쪽에서 거부하는 정적 가드 (hub §6.1, VITE-C4/VITE-C5)
  • React mount 이전 runtime config fetch(no-store) + 검증 게이트와 boot 실패/버전 불일치 분기 (FE-D012, hub §4.5/§6.3)
  • runtime config 검증 규칙 카탈로그(required key·URL protocol allowlist·int range·boolean parse·schema/contract version compat·unknown-key strict) (FE-OC-004, hub §6.4)
  • boot 실패 시 화면 노출 safe-field allowlist + redaction (hub §6.4)
  • environment별 rebuild fallback 규칙: 한 artifact를 여러 env에 재사용하지 않음 (FE-D013)
  • boot config 검증 시간 예산 FE-NFR-006(≤ 500ms, network delay 제외)의 측정 경계와 valid-config timing fixtureFE-GATE-004 pass condition의 timing 절반 (hub §14.2, §15.1)
  • FE-REG-CAPABILITY registry(src/contracts/capabilities.js)의 schema·초기 6행·single-owner 규칙 — capability flag 는 runtime config 키이므로 env registry owner 가 자연 owner다 (FE-D026, hub §5.11)
  • FE-GATE-033 capability default-off 게이트 — 기본 config 로 production build 했을 때 비활성 capability 의 adapter 가 어떤 chunk 에도 없음을 증명 (FE-NFR-020, hub §15.1)

제외 범위

의도적으로 제외 — 다른 owner 브랜치/계약 소유. 각 브랜치는 자신이 소유한 FE-OC-* 계약으로 표기(하위 FE-D*는 hub decision register 참조).

근거 (필수, 최소 1개+)

Source 정당화하는 결정
raw/official-docs/vite-build-tool-official VITE-C3(import.meta.env build-time 정적 치환) → build-time config는 재빌드로만 바뀐다는 D1/D2 전제; VITE-C4(오직 VITE_ prefix만 client 노출) → D3 노출 경계; VITE-C5(VITE_*에 secret 금지, 프로덕션 secret은 backend/serverless) → D3 secret 차단 규칙; VITE-C2(정적 자산 output) → static-only hosting fallback(D2) 전제
raw/project-notes/ca-skeleton-frontend-operational-contract 이 branch가 owner인 FE-D012/FE-D013 decision, FE-OC-004 계약, FE-REG-ENV(§5.4), boot order(§4.5)·boot sequence(§6.3)·runtime config 검증 규칙(§6.4)·boot 실패 safe-output(§6.4)·FE-RB-001 runbook(§16.1)의 project-decision 근거. 추가로 §14.2 FE-NFR-006(boot config validation ≤ 500ms, deterministic mocked fetch)·§15.1 FE-GATE-004(valid boot config validation timing 을 pass condition 에 포함)가 D8 시간 예산의 근거

TODO

각 항목 옆에 증거 등급 표기.

  • FE-REG-ENV registry schema + 초기 14 key row 구현 (src/contracts/env.js) — 등급: planned
  • build/runtime/secret 3분류 + secret-name 거부 정적 가드 구현 — 등급: planned
  • src/bootstrap/load-runtime-config.js — mount 이전 no-store fetch + boot 분기 구현 — 등급: planned
  • runtime config 검증 규칙(§6.4 8항) 구현 (schema 메커니즘은 FE-OC-007 브랜치 consume) — 등급: planned
  • boot 실패 safe-field allowlist + redaction 구현 — 등급: planned
  • boot invalid-config matrix 테스트(§20 Measurable completion) 작성 — 등급: planned
  • config schema test(FE-OC-004 minimum evidence) 작성 — 등급: planned
  • valid-config timing fixture 작성 — FE-NFR-006(≤ 500ms, mocked network delay 제외) 측정 + FE-GATE-004 timing report 산출 — 등급: planned

진행 중 메모

없음 — scaffolding 단계. repository 미생성이므로 모든 항목 planned.

결정 사항

각 결정의 근거는 아래 Decision Evidence Map과 1:1 대응. 대안·선택 조건 포함.

  • 2026-07-18: build-time public / runtime-public / secret 3분류 분리(FE-D012) / 이유: deploy마다 달라지는 public value(API endpoint 등)를 재빌드 없이 바꾸려면 build-time 정적 치환(import.meta.env)이 아닌 pre-render runtime config가 필요 / 검토한 대안: 모든 값을 build-time으로 고정(env별 재빌드) / 근거: VITE-C3, hub §6.1·FE-D012
  • 2026-07-18: runtime config fallback = env별 rebuild 허용하되 artifact 재사용 금지(FE-D013) / 이유: hosting이 atomic config publish를 못 할 때 deploy ambiguity를 제한 / 검토한 대안: 단일 artifact를 여러 env에 재사용 + build-time fallback / 근거: hub FE-D013
  • 2026-07-18: secret-name key 양쪽 registry 거부 + VITE_는 build metadata·non-secret 상수만 / 이유: VITE_*는 번들에 정적 치환되어 client에 노출되므로 secret 금지 / 검토한 대안: 관례 문서화만(정적 강제 없음) / 근거: VITE-C4, VITE-C5, hub §6.1
  • 2026-07-18: React mount 이전 runtime config fetch+검증 게이트(boot 2~4단계) / 이유: 잘못된 config로 product route를 mount하지 않기 위해 / 검토한 대안: mount 이후 lazy config load / 근거: hub §4.5 boot order, §6.3 sequence
  • 2026-07-18: runtime config 검증 8항 커버리지 + unknown-key strict default / 이유: config는 신뢰 경계 밖 입력이므로 boot 전 전량 검증 / 검토한 대안: 필수 key 존재만 확인 / 근거: hub §6.4 (schema 메커니즘은 FE-OC-007 위임)
  • 2026-07-18: boot 실패 화면 safe-field allowlist + endpoint/stack redaction / 이유: 실패 화면으로 endpoint·raw config·stack 유출 금지 / 검토한 대안: raw error 그대로 표시 / 근거: hub §6.4 (error kind 어휘는 FE-OC-008 위임)
  • 2026-07-18: 모든 public config는 FE-REG-ENV 경유(ad hoc import.meta.env 금지) / 이유: rename·compatibility 영향 추적 single owner / 검토한 대안: 파일마다 import.meta.env 직접 접근 / 근거: hub §5.1·§5.4, FE-D018
  • 2026-07-20: MAX_RETRY_ATTEMPTS 허용 범위를 retry cap 소유 결정에 정렬(02) / 이유: config가 owner 결정보다 넓은 값을 통과시키면 하류 client가 조용히 clamp 하게 되어 "설정한 값 ≠ 동작하는 값" 이 되므로, 경계 검증을 owner cap 과 동일하게 둔다 / 검토한 대안: config는 05를 통과시키고 API client가 clamp(설정-동작 괴리 허용) / 근거: raw/project-notes/ca-skeleton-frontend-operational-contract FE-D015(initial call 이후 최대 2회) — cap 소유는 FE-OC-009, 본 branch는 그 cap 을 config 경계에서 재선언만 하고 값 자체를 정하지 않음
  • 2026-07-20: boot config 검증 시간 예산 FE-NFR-006 은 "검증 구간만" 측정하며 mocked network delay 를 제외한다 / 이유: FE-GATE-004 pass condition 이 timing 을 포함하는데(hub §15.1) 측정 구간을 고정하지 않으면 fetch 대기 시간이 예산을 잠식해 gate 가 무의미해짐 / 검토한 대안: fetch 시작~mount 직전 end-to-end 측정(hosting/network 변동에 좌우) / 근거: raw/project-notes/ca-skeleton-frontend-operational-contract FE-NFR-006(§14.2, deterministic mocked fetch, ≤ 500ms excluding network delay), §15.1 FE-GATE-004

결정-근거 매핑

Supporting Claims: 공식 문서는 raw/official-docs/<slug>.md#<CLAIM> (백틱), project decision은 hub wikilink + FE-D/§ 참조. 위임 대상 sibling 브랜치는 소유 FE-OC-*로 표기(하위 FE-D*는 hub register).

Decision ID Decision 선택 조건 (언제 이 결정 / 언제 대안) Supporting Claims Evidence Strength Open Risk
D1 FE-D012 — deploy별 public value는 pre-render runtime config(/config.json), compiler value·asset identity는 build-time config로 분리 hosting이 HTML보다 먼저 runtime config를 atomic publish 가능 → runtime config 경로; 정적 파일만 제공 → D2 env별 rebuild fallback; SSR/edge 도입 → 본 계약 그대로 적용 않고 별도 project fork(hub §6.2) raw/official-docs/vite-build-tool-official.md#VITE-C3, raw/official-docs/vite-build-tool-official.md#VITE-C2; raw/project-notes/ca-skeleton-frontend-operational-contract FE-D012 §6.1 conditional-default + official-doc hosting이 runtime config atomic publish를 미지원하면 재검토(hub revisit trigger)
D2 FE-D013 — runtime config fallback은 env별 rebuild를 허용하되 한 artifact를 여러 env에 재사용하지 않음 atomic config publish 불가한 static-only hosting일 때만 env별 rebuild; runtime config endpoint 도입되면 단일 artifact + runtime fetch로 복귀. 어떤 경우에도 동일 artifact를 여러 env로 재배포 금지 raw/project-notes/ca-skeleton-frontend-operational-contract FE-D013; raw/official-docs/vite-build-tool-official.md#VITE-C3 conditional-default + project-decision runtime config endpoint 도입 시 재검토; artifact 재사용 시 deploy ambiguity 재발
D3 secret-name(SECRET/PASSWORD/PRIVATE_KEY/TOKEN) key를 build·runtime registry 모두 거부; VITE_ prefix는 build metadata·non-secret compile-time 상수만 항상 적용되는 invariant; auth owner가 browser storage를 꼭 써야 하는 경우에만 별도 threat model + owner evidence로 예외(skeleton default 아님, hub §6.1) raw/official-docs/vite-build-tool-official.md#VITE-C4, raw/official-docs/vite-build-tool-official.md#VITE-C5; raw/project-notes/ca-skeleton-frontend-operational-contract §6.1 official-doc 로그·디버그 등 다른 경로의 우발적 유출은 VITE-C4가 커버 안 함 → FE-OC-019 browser-security와 교차 필요
D4 runtime config + release manifest를 React mount 이전에 no-store fetch → 검증 → (valid) 조립·mount / (invalid) boot error shell / (mismatch) recovery UI. boot 2~4단계 실패 시 product route mount 안 함 config invalid → BOOT_CONFIG_FAILURE(product route mount 중단); version mismatch → DEPLOY_MISMATCH(controlled recovery, reload loop 금지); valid → mount. telemetry adapter 생성 실패는 non-blocking(console-safe fallback) raw/project-notes/ca-skeleton-frontend-operational-contract §4.5 boot order, §6.3 sequence, FE-OC-004 project-decision bounded refetch(최대 1회, §16.1)와 recovery UI 경계가 FE-OC-016/FE-OC-025 소유와 겹침
D5 runtime config 검증은 required-key·URL protocol allowlist(prod https)·int range(timeout/retry)·boolean strict parse·config schema version·API contract version·release/build ID coherence·unknown-key strict를 모두 커버 unknown key는 strict reject default; schema가 명시적으로 passthrough할 때만 additive key 허용. protocol allowlist는 prod https 강제, local 예외는 문서화된 경우만 raw/project-notes/ca-skeleton-frontend-operational-contract §6.4, FE-OC-004; schema 메커니즘은 raw/branch-notes/feature-runtime-schema-validation-contract (FE-OC-007) 위임 project-decision REQUEST_TIMEOUT_MS 경계 값은 hub 미규정(아래 impl §4 UNSUPPORTED_IMPL_DECISION); MAX_RETRY_ATTEMPTS 범위는 retry cap owner(FE-OC-009)에 정렬해 해소(02); version compat 정책은 FE-OC-023 위임
D6 boot 실패 화면은 safe-field(error.kind,error.code,buildId,configSchemaVersion,releaseId,supportReference)만 노출; endpoint·query·header·raw config·stack은 화면 금지 항상 적용되는 redaction invariant — 어떤 실패 종류에서도 forbidden field는 user-facing screen에 표시 안 함 raw/project-notes/ca-skeleton-frontend-operational-contract §6.4, FE-OC-004; error kind 어휘는 raw/branch-notes/feature-frontend-error-classification-boundary-contract (FE-OC-008) 위임 project-decision supportReference 생성 방식 미규정(impl §5 UNSUPPORTED_IMPL_DECISION); telemetry로의 상관 전송은 FE-OC-014 소유
D7 모든 build/runtime public config key는 FE-REG-ENV(src/contracts/env.js) 등록 후 사용; registry 밖 import.meta.env·config key 직접 사용은 violation. public-sensitive=browser 가시이나 로그·telemetry 원문 금지 항상 적용(hub FE-D018 8-registry single-owner invariant); code generation SSOT 채택 시 registry 형태 재검토 raw/project-notes/ca-skeleton-frontend-operational-contract §5.1 §5.4 FE-D018 project-decision registry diff·single-owner 강제와 compatibility 추적은 FE-OC-022/FE-OC-023 위임
D8 boot config 검증 시간 예산 FE-NFR-006(≤ 500ms) 은 검증 구간만 측정한다 — config 본문이 메모리에 있는 시점부터 normalized config 반환 또는 BOOT_CONFIG_FAILURE 확정까지. fetch·mocked network delay·mount 이후는 제외. FE-GATE-004 는 이 branch 가 config invalid matrix + valid-config timing fixture 를, schema 브랜치가 content-type/JSON/envelope/payload invalid matrix 를 각각 제공해 함께 PASS 시킨다 deterministic mocked fetch 환경에서 항상 측정(hub §14.2 context); 실제 network 를 타는 환경에서는 이 예산을 주장하지 않음(lab 값을 production 수치로 표현 금지) raw/project-notes/ca-skeleton-frontend-operational-contract §14.2 FE-NFR-006, §15.1 FE-GATE-004, FE-OC-004; invalid fixture 절반은 raw/branch-notes/feature-runtime-schema-validation-contract (FE-OC-007) 소유 — 해당 노트도 timing fixture 소유를 본 branch 로 귀속 project-decision 측정 시작점·통계(단일 실행 vs 중앙값)는 hub 미규정(impl §6 UNSUPPORTED_IMPL_DECISION); 검증 대상 fixture 규모가 커지면 500ms 예산 재검토 필요

구현 가이드

planned blueprint — frontend repository 미생성. 경로는 hub §4.6 Planned directory blueprint + §5.1 registry owner map에서 도출되어 grounded지만, 코드가 없으므로 전체가 planned다.

1. 환경 config registry FE-REG-ENV

Trace: D7 (hub §5.1·§5.4 FE-REG-ENV, FE-D018) + D3. Planned path src/contracts/env.js (§5.1 owner map).

  • UNSUPPORTED_IMPL_DECISION: registry의 JS 표현(row 배열 export const ENV_REGISTRY = [...] vs key→meta object map)은 hub가 schema 컬럼만 규정하고 JS 구조는 미규정 → row 배열 선택. trade-off: 순서 보존 + snapshot diff(FE-OC-022)가 단순.

초기 14 key(hub §5.4 그대로 — 신규 발명 아님):

Key Phase Classification Required Default Failure
VITE_BUILD_ID build public metadata yes none build fail
VITE_COMMIT_SHA build public metadata yes in CI local sentinel allowed release evidence fail
VITE_ROUTER_BASE_PATH build non-secret compile-time constant yes / route mount fail
VITE_RUNTIME_CONFIG_URL build non-secret compile-time constant yes /config.json boot fail
APP_ENV runtime public yes none boot fail
API_BASE_URL runtime public-sensitive yes none boot fail
REQUEST_TIMEOUT_MS runtime public no 10000 invalid value boot fail
MAX_RETRY_ATTEMPTS runtime public no 2 after initial (허용 범위 02, cap owner FE-OC-009) invalid value boot fail
TELEMETRY_ENABLED runtime public yes false invalid value boot fail
TELEMETRY_ENDPOINT runtime public-sensitive conditional none telemetry degrade
AUTH_MODE runtime public yes external unsupported mode boot fail
CONFIG_SCHEMA_VERSION runtime public yes none compatibility fail
API_CONTRACT_VERSION runtime public yes none compatibility fail
RELEASE_MANIFEST_URL runtime public yes /release-manifest.json mismatch detection degrade/fail per policy
  • public-sensitive(예: API_BASE_URL, TELEMETRY_ENDPOINT) = browser 가시이나 로그·telemetry에 원문 금지 (hub §5.4). secret 분류 아님.
  • ad hoc 사용 위반(hub §5.1): registry 없는 import.meta.env 또는 config key 사용.

2. runtime / secret 3분류 + secret-name 거부 가드

Trace: D1 (FE-D012, hub §6.1, VITE-C3) + D3 (VITE-C4, VITE-C5, hub §6.1).

  • UNSUPPORTED_IMPL_DECISION: secret-name 거부 매칭 알고리즘(case-insensitive substring /(SECRET|PASSWORD|PRIVATE_KEY|TOKEN)/i vs 정확 word 매칭) 미규정 — hub는 4개 토큰만 나열(§6.1) → case-insensitive substring(fail-safe) 선택. trade-off: TOKENIZER 같은 정당한 이름 false-positive 위험 → 문서화된 명시적 예외 목록으로 완화.
Class 예시 Browser 가시 변경 메커니즘 Cache 규칙
build-time public VITE_BUILD_ID, VITE_COMMIT_SHA, VITE_ROUTER_BASE_PATH yes rebuild(정적 치환) bundled compiler behavior·asset identity만
runtime public API_BASE_URL, public feature flag, TELEMETRY_ENDPOINT yes runtime config publish no-store React mount 이전 검증
secret client secret, private key, DB credential, refresh token material 번들 금지 server/auth owner N/A frontend env·bundle·HTML 어디에도 금지
  • VITE_ prefix는 build metadata + non-secret compile-time 상수(base path, /config.json 위치)에만 (hub §6.1, VITE-C4).
  • 이름에 SECRET/PASSWORD/PRIVATE_KEY/TOKEN 포함 key는 build·runtime registry 양쪽에서 거부 (hub §6.1). 프로덕션 secret은 backend/serverless 소관 (VITE-C5).

3. mount 이전 runtime config 로더 + boot 분기

Trace: D4 (hub §4.5 boot order, §6.3 sequence). Planned paths src/bootstrap/load-runtime-config.js, src/bootstrap/composition-root.js, src/bootstrap/main.jsx (§4.6). 의존: build/import.meta.env 노출은 raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract (FE-OC-003); composition root 조립은 raw/branch-notes/feature-frontend-clean-architecture-layering-contract (FE-OC-002) 소유.

  • UNSUPPORTED_IMPL_DECISION: (a) boot error shell 컴포넌트 명/경로(예: presentation/boundaries/BootErrorShell.jsx) — hub는 "boot error shell" 개념만, 명명/경로 미규정 → presentation/boundaries 하위에 두어 layering(FE-OC-002) 위반 회피. (b) pre-mount config fetch 클라이언트(raw fetch vs shared client) — boot 2단계 시점엔 shared client(FE-OC-006)가 아직 조립 전 → raw fetch 선택. trade-off: shared client의 timeout/retry 정책은 config 로드에 적용 안 됨(부트 전용 최소 fetch).

본 branch 소유 구간은 단계 번호가 아니라 의미로 정의한다: "runtime config 취득 + 검증 완료까지, React mount 이전". 그 앞(build identity 읽기)과 뒤(adapter 조립·mount)는 타 owner 구간이다. hub 의 두 절이 나열 순서를 서로 다르게 쓰므로(§4.5 는 config 검증 → release manifest 정합성, §6.3 sequence 는 두 fetch → 검증) 번호 기반 참조는 깨지기 쉽다. 아래 목록은 §6.3 실행 순서를 따르고, 각 행에 hub §4.5 번호를 명시 매핑한다.

실행 순서(hub §6.3 기준) hub §4.5 번호 Owner
build identity 읽기 (build-time config, §1) 1 build/toolchain (FE-OC-003) — 본 branch 는 key 분류만
runtime config fetch — GET {VITE_RUNTIME_CONFIG_URL} no-store 2 본 branch
release manifest fetch — GET {RELEASE_MANIFEST_URL} no-store 4의 입력 취득 본 branch (정합성 판정 자체는 FE-OC-016)
config envelope·schema·compatibility 검증 (§4) 3 본 branch (schema 메커니즘은 FE-OC-007 consume)
registry snapshot → auth adapter → HTTP/storage/telemetry/query-cache adapter → application facade → router → React root mount 510 composition root (FE-OC-002)

분기(hub §6.3):

  • valid & compatible → normalized public config로 dependency 조립 + mount.
  • invalid configBOOT_CONFIG_FAILURE → boot error shell, product route mount 안 함. automatic refetch 최대 1회(hub §16.1).
  • version mismatchDEPLOY_MISMATCH → controlled recovery UI, reload loop 금지. (recovery UI 상세는 raw/branch-notes/feature-frontend-release-cache-rollback-contract 소유 — 본 branch는 트리거/분기까지만.)
  • telemetry adapter 생성 실패 → console-safe fallback로 계속(boot 실패 아님, hub §4.5).

4. runtime config 검증 규칙

Trace: D5 (hub §6.4). schema 구성·parse 메커니즘은 raw/branch-notes/feature-runtime-schema-validation-contract (FE-OC-007) 위임 — 본 §는 무엇을 검증하고 어떤 boot 결과로 이어지는지만.

  • UNSUPPORTED_IMPL_DECISION: REQUEST_TIMEOUT_MS 정수 범위(제안 100060000)는 hub가 default(10000)만 주고 경계 미규정 → 0/음수 timeout 방지용으로 제안. trade-off: 상한 60000 은 임의값이며 api-client owner(FE-OC-009)가 total timeout 정책을 lock 할 때 재확인 필요.
  • 해소됨(구 UNSUPPORTED_IMPL_DECISION): MAX_RETRY_ATTEMPTS 허용 범위는 02raw/project-notes/ca-skeleton-frontend-operational-contract FE-D015(initial call 이후 최대 2회)의 cap 을 config 경계에서 그대로 재선언한다. 이전 초안의 0–5 는 owner cap 보다 넓어 "config 는 통과, client 는 clamp" 하는 설정-동작 괴리를 만들었으므로 폐기. cap 값의 owner 는 FE-OC-009 이고 본 branch 는 값을 정하지 않으므로, cap 이 개정되면 이 범위도 따라 개정한다(본 노트 단독 변경 금지).

검증 MUST 커버(hub §6.4):

  • required key 존재 (§1 Required=yes 전부)
  • URL protocol allowlist — prod policy는 https, local 예외는 문서화된 경우만
  • timeout/retry 정수 범위 — REQUEST_TIMEOUT_MS 100060000(제안), MAX_RETRY_ATTEMPTS 02(cap owner FE-OC-009 에 정렬)
  • boolean parse — truthy-string 모호성 없이("false"가 true 되지 않게)
  • config schema version 호환 (CONFIG_SCHEMA_VERSION)
  • API contract version 호환 (API_CONTRACT_VERSION)
  • provider가 둘 다 노출하면 release/build ID coherence
  • unknown-key 정책: default strict, schema가 명시적 passthrough일 때만 additive 허용

compat 실패 시 migration/version bump 정책은 raw/branch-notes/feature-frontend-contract-compatibility-governance (FE-OC-023) 위임.

5. boot 실패 safe-output (redaction)

Trace: D6 (hub §6.4). normalized error kind 어휘와 raw body/stack UI 유출 catalog는 raw/branch-notes/feature-frontend-error-classification-boundary-contract (FE-OC-008) 위임.

  • UNSUPPORTED_IMPL_DECISION: supportReference 생성 방식(무작위 correlation id vs releaseId+timestamp) 미규정 — hub는 field만 나열 → 무작위 opaque id 선택. trade-off: deploy timing 유출 방지하나, 트리아지용으로 telemetry event와 매핑되어야 함(FE-OC-014 소유).

boot error shell 노출 허용 field(allowlist, hub §6.4):

error.kind
error.code
buildId
configSchemaVersion
releaseId (if present)
supportReference

화면 금지: endpoint, query, header, raw config object, stack (hub §6.4).

6. boot config 검증 시간 예산 (FE-NFR-006) + FE-GATE-004 소유 분할

Trace: D8 (hub §14.2 FE-NFR-006 — deterministic mocked fetch, ≤ 500ms excluding network delay; hub §15.1 FE-GATE-004 pass condition). invalid fixture 의 나머지 절반(content-type/JSON/envelope/payload)은 raw/branch-notes/feature-runtime-schema-validation-contract (FE-OC-007) 소유 — 해당 노트도 timing fixture 소유를 본 branch 로 귀속시키므로 양방향 일치.

  • UNSUPPORTED_IMPL_DECISION: 측정 시작·종료 지점을 hub 가 규정하지 않음("excluding network delay" 만 명시) → 시작 = config 원문(text/object)이 validator 에 전달되는 시점, 종료 = normalized config 반환 또는 BOOT_CONFIG_FAILURE 확정 시점으로 고정. trade-off: JSON parse 비용이 예산 안에 포함되어 보수적으로 측정되지만, transport 구현(fetch·캐시·mock)에 무관한 재현 가능 구간이 된다.
  • UNSUPPORTED_IMPL_DECISION: 회차·통계(단일 실행 vs 다회 중앙값)를 hub 가 미규정 → 동일 fixture 5회 실행의 중앙값을 판정값으로 쓰고 최댓값도 report 에 함께 기록. trade-off: CI 노이즈로 인한 flake 를 줄이지만 tail latency 를 판정에서 제외하므로, 최댓값이 예산의 2배를 넘으면 report 를 근거로 재검토한다.

측정 대상(무엇을 재는가). FE-NFR-006검증 구간만 잰다. 포함: required-key 검사, URL protocol allowlist, int range, boolean strict parse, config/API version 호환 비교, release/build ID coherence, unknown-key strict 판정(§4 8항 전부). 제외: GET {VITE_RUNTIME_CONFIG_URL}·GET {RELEASE_MANIFEST_URL} 의 network 대기, mock 이 주입한 인위적 지연, 검증 이후의 adapter 조립·mount(그 구간은 FE-OC-002 소유이며 본 예산의 대상이 아님).

fixture 가 network delay 를 배제하는 방법. transport 를 deterministic mock 으로 대체하고(hub §14.2 context), config 본문을 이미 메모리에 있는 값으로 validator 에 직접 전달한다. 즉 fixture 는 fetch 를 거치지 않거나, 지연을 주입한 mock 을 쓰더라도 타이머를 fetch resolve 이후에 시작한다. 따라서 mock 지연을 늘려도 측정값이 변하지 않아야 하며, 이 불변식 자체를 fixture 의 self-check 로 둔다(지연 0ms 와 지연 200ms 두 실행의 측정값 차이가 노이즈 범위 내).

valid-config fixture 형태. §1 registry 의 runtime key 10개를 모두 채운 valid config 1건(= 실제 boot 가 받는 최대 폭). 판정: 중앙값 ≤ 500ms.

FE-GATE-004@1 소유 분할 (hub §15.1 의 Covered FE-OC 가 다수라 fixture 소유를 명시해야 중복·누락이 없다 — 어느 계약이 묶여 있는지는 hub §15.1 소유):

FE-GATE-004 구성요소 소유
config invalid matrix (required key 부재·protocol 위반·range 위반·boolean 모호·unknown key·version 비호환) 본 branch (FE-OC-004)
valid-config timing fixture + timing report (FE-NFR-006) 본 branch (FE-OC-004)
content-type / JSON / envelope / payload invalid matrix FE-OC-007
각 invalid 입력의 기대 error kind 어휘 FE-OC-008
version 비호환 시 migration 판정 FE-OC-023

gate 는 두 소유자의 fixture 가 모두 있어야 PASS 하므로, 어느 한쪽만 준비된 상태에서 FE-GATE-004 를 PASS 로 올리지 않는다.

엣지·실패·의존

검증해야 할 주장

Claim Why uncertain How to verify Status
build/runtime/secret 분류가 실제로 강제됨(secret-name key가 양쪽 registry에서 거부) 코드·정적 가드 미존재, 규칙 문서만 있음 config schema test + secret-name 거부 negative fixture (FE-OC-004 minimum evidence) needs-confirmation
boot invalid-config matrix의 각 invalid 입력이 기대 boot 결과(BOOT_CONFIG_FAILURE/DEPLOY_MISMATCH/boot fail)로 매핑 다양한 실패 조합의 실제 boot 분기 미검증 boot invalid-config matrix 테스트(§20 Measurable completion) needs-confirmation
runtime config가 no-store로 fetch되고 React mount 이전에 검증됨(실패 시 product route mount 안 됨) 조립 순서·no-store가 코드로 보장되는지 미검증 boot ordering 통합 테스트(mount 이전 fetch·실패 시 route 미mount 확인) needs-confirmation
boot 실패 화면이 safe-field만 노출(endpoint·raw config·stack 미유출) redaction 강제 여부 미검증 boot error shell redaction negative fixture needs-confirmation
capability flag 6개가 전부 OFF인 기본 config 로 build 하면 대응 adapter 가 번들에 없다 정적 import 하나면 조용히 포함됨. tree-shaking 이 보장하지 않음 FE-GATE-033 capability bundle report — 각 adapter 모듈 경로가 어떤 chunk 에도 없는지 대조 planned
capability 전부 OFF 일 때 initial JS gzip 증가가 0 KiB 다 FE-NFR-001 예산을 신규 기능이 잠식할 수 있음 bundle report 비교 — 확장 전후 initial chunk 크기 (FE-NFR-020) planned
한 artifact를 여러 env에 재사용하지 않음(FE-D013) 배포 프로세스 속성 — unit test로 완전 증명 불가 배포 파이프라인 assertion + env별 artifact hash 대조(문서화된 deploy check) needs-confirmation
non-VITE_ build 변수가 client 번들로 유출되지 않음 번들 정적 치환 경계는 실제 빌드로만 확인 build 후 bundle scan (FE-OC-019 browser-security와 교차) needs-confirmation
valid config 검증이 FE-NFR-006 예산(≤ 500ms, mocked network delay 제외) 안에 들어옴 코드·검증 로직 미존재. 8항 검증 + schema 라이브러리(FE-OC-007)의 deep clone/parse 비용이 미측정이라 500ms 가 여유인지 빠듯한지 알 수 없음 runtime key 10개를 채운 valid-config timing fixture 5회 실행의 중앙값 측정(impl §6) → FE-GATE-004 timing report needs-confirmation
timing fixture 의 측정값이 mocked network delay 에 영향받지 않음(예산이 검증 구간만 잰다) 측정 시작점이 fetch resolve 이후인지 코드로 강제되는지 미검증 동일 fixture 를 mock 지연 0ms / 200ms 로 각각 실행해 측정값 차이가 노이즈 범위 내인지 확인(impl §6 self-check) needs-confirmation

관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때)

/coverage가 채우는 생성물이며 손으로 유지하지 않는다.

관심사 상태 owner 심각도 근거
TODO — /coverage 실행 전 missing (없음) 미평가 TODO

마주친 문제

없음 — scaffolding 단계

묶음 (이 branch에서 파생된 자료)

가져온 프로젝트 계약

Ref Owner 요약 Branch 적용
FE-GATE-004@1 raw/branch-notes/feature-runtime-schema-validation-contract invalid fixture 가 예상 kind 로 거부되지 않으면 merge 를 MUST 차단 import 참조로 적용
FE-OC-002@1 raw/branch-notes/feature-frontend-clean-architecture-layering-contract domain <- application <- presentation 의존 방향과 application-owned output port를 MUST 지킴 import 참조로 적용
FE-OC-003@1 raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract package manager, engine, lockfile, source language, checkJs command를 한 곳에서 MUST 고정 import 참조로 적용
FE-OC-007@1 raw/branch-notes/feature-runtime-schema-validation-contract JSON envelope와 payload는 boundary에서 runtime schema를 MUST 통과 import 참조로 적용
FE-OC-008@1 raw/branch-notes/feature-frontend-error-classification-boundary-contract 모든 failure는 stable frontend error kind로 MUST 정규화하고 raw body·stack을 UI에 노출하면 안 됨 import 참조로 적용
FE-OC-009@1 raw/branch-notes/feature-api-client-response-envelope-contract retry는 safe/idempotent request에 한정하고 cap·jitter·Retry-After를 MUST 적용 import 참조로 적용
FE-OC-014@1 raw/branch-notes/feature-frontend-observability-logging-trace-contract telemetry는 best-effort이며 render·API success를 차단하면 안 되고 PII·token을 전송하면 안 됨 import 참조로 적용
FE-OC-016@1 raw/branch-notes/feature-frontend-release-cache-rollback-contract HTML, asset, runtime config, release manifest cache policy를 MUST 구분 import 참조로 적용
FE-OC-019@1 raw/branch-notes/feature-frontend-browser-security-boundary-contract browser bundle에 secret을 넣지 않고 untrusted HTML injection을 기본 금지 import 참조로 적용
FE-OC-022@1 raw/branch-notes/feature-frontend-contract-registry-governance 8개 registry는 single primary owner와 compatibility impact를 MUST 기록 import 참조로 적용
FE-OC-023@1 raw/branch-notes/feature-frontend-contract-compatibility-governance API/config/storage/release schema의 breaking change는 migration 또는 version bump 없이 배포하면 안 됨 import 참조로 적용
FE-OC-025@1 raw/branch-notes/feature-frontend-operational-runbook-contract boot, chunk mismatch, API degradation, telemetry failure, rollback runbook을 MUST 유지 import 참조로 적용

Sub-branches (세부 작업)

없음 — scaffolding 단계

오류 기록 (이 branch 작업 중 발생)

없음 — scaffolding 단계

면접 준비 (이 작업에서 나올 수 있는 면접 질문)

없음 — scaffolding 단계

강의 (이 작업을 위해 학습한 강의)

없음 — scaffolding 단계

job-posting tie-ins (이 작업에서 파생된 글감)

없음 — scaffolding 단계

관련 일일 노트

없음 — scaffolding 단계

완료 후 정리

  • PR 링크:
  • 리뷰 메모:
  • 머지 결과 / 배포 환경:
  • wiki 추출 대상 (verified만, wiki/projects/로만 추출):
    • actually-implemented 항목:
    • locally-verified 항목:
    • prod-verified 항목:
  • 추출하지 않을 항목 (planned / documented-only / abandoned):