diff --git a/frontend/src/routes/documents/[id]/+page.svelte b/frontend/src/routes/documents/[id]/+page.svelte index e124be1..8410728 100644 --- a/frontend/src/routes/documents/[id]/+page.svelte +++ b/frontend/src/routes/documents/[id]/+page.svelte @@ -77,10 +77,14 @@ let treeGroupIndex = $derived(treeGroups ? groupKeyByChunkId(treeGroups) : null); let treeExpanded = $state({}); // key 없으면 접힘(기본 전부 접힘). Svelte5 deep-proxy 반응형. function toggleTreeGroup(key) { treeExpanded[key] = !treeExpanded[key]; } + // sections 로딩 완료 플래그 — 미완 동안 fallback 풀-문서 뷰어를 띄우면, 곧 절뷰로 교체되며 + // 풀-문서 이미지가 '살짝 보였다 사라지는' 플래시가 난다(절 보유 문서). 로딩 중엔 skeleton. + let sectionsLoaded = $state(false); async function loadSections() { const reqId = docId; try { const r = await api(`/documents/${reqId}/sections`); if (reqId === docId) sections = r?.sections ?? []; } catch { if (reqId === docId) sections = []; } + finally { if (reqId === docId) sectionsLoaded = true; } } onMount(async () => { @@ -149,7 +153,9 @@ const gk = idx.get(sel); if (gk) untrack(() => { treeExpanded[gk] = true; }); }); - let selectedItem = $derived(outline.find((it) => it.section.chunk_id === selectedSectionId) ?? outline[0] ?? null); + // selectedSectionId 미설정(초기) 시 defaultSelId(첫 본문 Part)로 바로 해석 — outline[0](표지/front-matter) + // 를 잠깐 렌더했다 effect 가 defaultSelId 로 바꾸는 절뷰 내부 플래시 차단. + let selectedItem = $derived(outline.find((it) => it.section.chunk_id === (selectedSectionId ?? defaultSelId)) ?? outline[0] ?? null); let selectedSection = $derived(selectedItem?.section ?? null); let selIdx = $derived(outline.findIndex((it) => it.section.chunk_id === selectedItem?.section?.chunk_id)); // 절 본문 = 청크 원문(it.bodyText, window 조각 합본) 직접 렌더. 과거 char_start 로 md_content 를 @@ -435,7 +441,10 @@ - {#if useSectionView} + {#if !sectionsLoaded} + + + {:else if useSectionView}