From 1bfc9ee12c4fafe9938d22712e613c3c0d6f09d5 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 6 Sep 2026 12:21:32 +0900 Subject: [PATCH] =?UTF-8?q?fix(B06):=20=EB=93=B1=EB=A1=9D=ED=91=9C?= =?UTF-8?q?=EC=97=90=20`extraspan`=20=EC=9D=B4=20=EB=B9=A0=EC=A0=B8=20B06?= =?UTF-8?q?=20=ED=99=94=EB=A9=B4=EC=9D=B4=20=ED=86=B5=EC=A7=B8=EB=A1=9C=20?= =?UTF-8?q?=EC=95=88=20=EB=9C=A8=EB=8D=98=20=ED=9A=8C=EA=B7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 캐시·세션 일원화에서 조정창 값 8종을 옮기며 다단 구간값(`extraspan`)을 등록표에 빠뜨렸다. 표에 없는 이름을 꺼내다 예외가 나 페이지 렌더가 통째로 실패했고 화면에는 「준비 중인 페이지입니다」만 떴다(화면 확인으로 발견). - `extraspan` 을 등록표에 넣음. - 표에 없는 이름은 이제 **예외 대신 저장 건너뛰기** — 그 값만 안 남고 화면은 선다. 콘솔에 한 번 알려 표에 줄을 넣게 한다. - B06 이 키를 만들 때 쓰던 형변환을 없앰 — 앞으로 등록표에 없는 이름은 컴파일에서 걸린다. 같은 사고가 화면까지 가지 않는다. Co-Authored-By: Claude Opus 5 (1M context) --- A00_Common/b_page_state.ts | 23 +++++++++++++++++++---- B06_Section/B06_Section_UI_Page.ts | 6 ++++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/A00_Common/b_page_state.ts b/A00_Common/b_page_state.ts index 83bf030a..2a48d6d7 100644 --- a/A00_Common/b_page_state.ts +++ b/A00_Common/b_page_state.ts @@ -124,6 +124,7 @@ export const STATE_REGISTRY = { extrawall: { bucket: "draft", scope: "route", legacy: (p, r) => `b06:extrawall:${p}:${r}` }, fordadjust: { bucket: "draft", scope: "route", legacy: (p, r) => `b06:fordadjust:${p}:${r}` }, boxadjust: { bucket: "draft", scope: "route", legacy: (p, r) => `b06:boxadjust:${p}:${r}` }, + extraspan: { bucket: "draft", scope: "route", legacy: (p, r) => `b06:extraspan:${p}:${r}` }, /* ── ④ 계산 결과 ─────────────────────────────────────────────────────── */ /** 노선·종단 최신 응답. 페이지를 오갈 때 이 값으로 먼저 그린다. */ @@ -146,8 +147,21 @@ export const STATE_REGISTRY = { export type StateName = keyof typeof STATE_REGISTRY; -function entryOf(name: StateName): StateEntry { - return STATE_REGISTRY[name] as StateEntry; +const warnedNames = new Set(); + +/** + * 등록표에서 한 줄을 꺼낸다. 표에 없는 이름이면 **화면을 죽이지 않고** null 을 돌려준다 — + * 그 값만 저장이 안 될 뿐 페이지는 그대로 선다(2026-09-06: `extraspan` 이 빠져 B06 이 + * 통째로 안 뜬 적이 있다). 대신 콘솔에 한 번 알려 표에 줄을 넣게 한다. + */ +function entryOf(name: StateName): StateEntry | null { + const entry = STATE_REGISTRY[name] as StateEntry | undefined; + if (entry) return entry; + if (!warnedNames.has(name)) { + warnedNames.add(name); + console.warn(`[page-state] 등록표에 없는 이름입니다 — 저장하지 않습니다: ${name}`); + } + return null; } /** @@ -160,6 +174,7 @@ export function stateKey( routeId?: number | string | null, ): string | null { const entry = entryOf(name); + if (!entry) return null; const suffix = entry.version && entry.version > 1 ? `-v${entry.version}` : ""; const head = `aislo:${entry.bucket}:${name}${suffix}`; if (entry.scope === "global") return head; @@ -194,7 +209,7 @@ function migrate( projectId?: string | null, routeId?: number | string | null, ): void { - const legacy = entryOf(name).legacy?.(projectId ?? undefined, routeId ?? undefined); + const legacy = entryOf(name)?.legacy?.(projectId ?? undefined, routeId ?? undefined); if (!legacy || legacy === key) return; const old = readRaw(legacy); if (old !== null && readRaw(key) === null) writeRaw(key, old); @@ -258,7 +273,7 @@ export function clearState( /** 등록표에서 한 통에 속한 이름만 고른다. */ export function namesInBucket(bucket: StateBucket): StateName[] { return (Object.keys(STATE_REGISTRY) as StateName[]).filter( - (name) => entryOf(name).bucket === bucket, + (name) => entryOf(name)?.bucket === bucket, ); } diff --git a/B06_Section/B06_Section_UI_Page.ts b/B06_Section/B06_Section_UI_Page.ts index fca207d7..94ef47c5 100644 --- a/B06_Section/B06_Section_UI_Page.ts +++ b/B06_Section/B06_Section_UI_Page.ts @@ -1,6 +1,6 @@ import { CURRENT_PROJECT_ID_KEY, ROUTES } from "@config/config_frontend"; import { leaveForDashboard } from "../A00_Common/b_missing_data_guard"; -import { stateKey, type StateName } from "../A00_Common/b_page_state"; +import { stateKey } from "../A00_Common/b_page_state"; import { navigateTo } from "../A00_Common/router"; import { createButton, createInputField, showToast } from "@ui/ui_template_elements"; import { createWorkflowLayout } from "@ui/ui_template_workflow_layout"; @@ -401,7 +401,9 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise { const stationControls = createStationControls({ // 키는 등록표(`b_page_state`)가 만든다 — 이름만 넘기면 통·범위·옛 키 이관이 따라온다. - sessionKey: (kind) => stateKey(kind as StateName, projectId, currentRouteId), + // 형변환을 두지 않는다: 등록표에 없는 이름을 쓰면 **컴파일에서** 걸린다 + // (2026-09-06 `extraspan` 누락으로 B06 이 안 뜬 뒤 막음). + sessionKey: (kind) => stateKey(kind, projectId, currentRouteId), refreshCard: (chainageM) => sectionView.refreshCard(chainageM), detail: () => sectionDetail, crossHalfWidth,