perf(전처리): 343-1 같은 지형 파일 다시 올림 = 전처리 결과 살림 · 다시 돌 때 점군 안 풂 · 도엽 병합 · 국가 GIS · 타일 기억 열쇠

- B03 재올림 — 지형 파일이 source_identity.json 과 같으면 B04 폴더 · 지표면 DB 행 남기고 단계 표시만 되돌림
- 확인 창 「처음부터 다시」 따로 고름(fresh_start) · 409 응답에 preprocess_kept
- B04 다시 돎 — 점 수 · 평균 Z 를 structured_stats.json 에 · xyz 는 쓸 때만 풂
- 도엽 병합 열쇠 = 도엽 번호 목록 · 국가 GIS 열쇠 = 범위 · 좌표계
- 지도 타일 메모리 기억 열쇠에 mtime · 크기
- 시험 test_343_1_preprocess_keep 13건

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
This commit is contained in:
2026-10-16 11:00:04 +09:00
co-authored by Claude Opus 5.5
parent 2879f9bea9
commit cf5de56418
9 changed files with 449 additions and 31 deletions
+18 -5
View File
@@ -83,9 +83,11 @@ export function confirmReplaceUpload(slotLabel: string, fileName: string): Promi
* 되돌릴 수 없는 삭제라 확인 없이는 진행하지 않는다(2026-09-08 사용자 지시).
* 자동 절차는 이 자리를 지나지 않는다 — 서버가 확인을 켜고 부른다.
*/
async function askReplaceOutputs<T>(run: (confirmReplace: boolean) => Promise<T>): Promise<T> {
async function askReplaceOutputs<T>(
run: (confirmReplace: boolean, freshStart: boolean) => Promise<T>,
): Promise<T> {
try {
return await run(false);
return await run(false, false);
} catch (error) {
if (!(error instanceof ReplaceOutputsConfirmRequired)) throw error;
const detail = error.targets.length
@@ -99,7 +101,16 @@ async function askReplaceOutputs<T>(run: (confirmReplace: boolean) => Promise<T>
되돌릴 수 없습니다. 계속할까요?`,
);
if (!agreed) throw new Error("업로드를 취소했습니다 — 기존 결과는 그대로 있습니다.");
return await run(true);
// 지형 파일이 그대로면 전처리 결과는 살린다 — 「처음부터 다시」는 여기서 따로 고른다.
const freshStart =
error.preprocessKept &&
window.confirm(
`같은 지형 파일이라 전처리 결과(지표면)는 살려 다시 씁니다.
전처리까지 처음부터 다시 할까요?
[확인] 처음부터 다시 · [취소] 전처리 결과 살림`,
);
return await run(true, freshStart);
}
}
@@ -123,7 +134,7 @@ export async function uploadOneFile(
const fingerprint = state.uploadSessionId ? null : await fileFingerprint(file);
let session = state.uploadSessionId;
if (!session) {
const created = await askReplaceOutputs((confirmReplace) =>
const created = await askReplaceOutputs((confirmReplace, freshStart) =>
createUploadSession(
projectId,
file,
@@ -132,6 +143,7 @@ export async function uploadOneFile(
completeUpload,
lasFree,
confirmReplace,
freshStart,
),
);
if (created.already_uploaded) {
@@ -184,7 +196,7 @@ export async function uploadOneFile(
}
}
const response = await askReplaceOutputs((confirmReplace) =>
const response = await askReplaceOutputs((confirmReplace, freshStart) =>
finalizeUploadSession(
projectId,
session,
@@ -193,6 +205,7 @@ export async function uploadOneFile(
fingerprint,
lasFree,
confirmReplace,
freshStart,
),
);
localStorage.removeItem(storageKey);