From cdb9799e648070a0e557e4946a4e3508c7248e04 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 6 Sep 2026 18:38:04 +0900 Subject: [PATCH] =?UTF-8?q?fix(B05):=20=EA=B5=AC=EC=A1=B0=EB=AC=BC=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=EC=9D=B4=20=ED=8C=90=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EB=95=8C=EB=AC=B8=EC=97=90=20=ED=86=B5=EC=A7=B8=EB=A1=9C=20?= =?UTF-8?q?=EC=82=AC=EB=9D=BC=EC=A7=80=EB=8D=98=20=EA=B2=83=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 화면 진입 때 받은 판번호로 저장해, 그 사이 정본이 한 번이라도 바뀌면(다른 창 저장·노선 재계산) 409 로 거절되고, 실패 처리가 세션 초안까지 지워 사용자가 넣은 구조물이 사라졌음. - 판번호를 **쓰기 직전에** 서버에서 다시 받아 씀. - 저장이 실패해도 세션 초안·화면 목록을 지우지 않음(다시 [저장]하면 됨). 실화면 검증: 고치기 전 구조물 추가 후 [저장] → 정본 0건. 고친 뒤 → 정본 1건, 2건. Co-Authored-By: Claude Opus 5 (1M context) --- B05_Profile/B05_Profile_UI_Page_Structures.ts | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/B05_Profile/B05_Profile_UI_Page_Structures.ts b/B05_Profile/B05_Profile_UI_Page_Structures.ts index 61cde2be..efb7662f 100644 --- a/B05_Profile/B05_Profile_UI_Page_Structures.ts +++ b/B05_Profile/B05_Profile_UI_Page_Structures.ts @@ -248,7 +248,16 @@ export function createStructuresBridge(deps: StructuresBridgeDeps) { async function persistStructures(next: StructureInstance[]): Promise { if (deps.isRestoring()) return; try { - const saved = await saveStructures(deps.projectId, structureRevision, next); + // 판번호는 **쓰기 직전에** 서버에서 다시 받는다. 진입 때 받은 값으로 보내면, + // 화면이 떠 있는 동안 정본이 한 번이라도 바뀌었을 때(다른 창 저장·노선 재계산) + // 409 로 거절되고 아래 실패 처리가 초안을 지워 **사용자가 넣은 구조물이 통째로 + // 사라졌다**(2026-09-06 실측: B06에서 구조물을 넣고 [저장]해도 정본에 안 남음). + const current = await fetchStructures(deps.projectId).catch(() => null); + const saved = await saveStructures( + deps.projectId, + current ? current.revision : structureRevision, + next, + ); structureRevision = saved.revision; writePending(null); // 서버가 새 항목에 식별자를 붙이므로 그 결과로 화면 목록을 맞춘다. @@ -263,14 +272,15 @@ export function createStructuresBridge(deps: StructuresBridgeDeps) { ); } } catch (error) { + // 실패해도 **초안은 지우지 않는다** — 지우면 사용자가 넣은 구조물이 사라진다 + // (2026-09-06 정정). 화면 목록도 그대로 두고 다시 [저장]하면 된다. if (error instanceof StructureConflictError) { - await refreshStructuresFromServer(); - showToast("다른 창에서 구조물이 먼저 저장되어 최신 내용으로 되돌렸습니다.", "error"); + showToast( + "다른 창에서 구조물이 먼저 저장돼 이번 저장을 건너뛰었습니다. 다시 [저장]해 주세요.", + "error", + ); return; } - // 저장이 거절되면 화면에만 남은 항목은 식별자가 없어 고치지도 지우지도 못한다. - // 서버 정본으로 되돌려 화면과 정본을 다시 일치시킨다(2026-08-16 크로스체크 지적 1). - await refreshStructuresFromServer(); showToast(error instanceof Error ? error.message : "구조물 저장에 실패했습니다.", "error"); } }