From 0d66107743a7952053471eea9f6b9def5c11a629 Mon Sep 17 00:00:00 2001 From: Hyungi Ahn Date: Tue, 28 Apr 2026 13:14:52 +0900 Subject: [PATCH] =?UTF-8?q?fix(study):=20=ED=9A=8C=EC=B0=A8=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20race=20=EC=A0=9C=EA=B1=B0=20=E2=80=94=20$effect=20?= =?UTF-8?q?=E2=86=92=20=EB=AA=85=EC=8B=9C=EC=A0=81=20onchange=20=ED=95=B8?= =?UTF-8?q?=EB=93=A4=EB=9F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit $effect 가 examRounds fetch 전 첫 실행되며 f_qnum=1 로 reset 하는 race 가 이전 fix(lastExamRound sync) 만으로 완전히 막히지 않음. effect 자체를 제거하고 select onchange + applyNewRound 에서 명시 호출하는 onRoundChange() 로 변경. examRounds 미적재 시 (length=0) 는 skip — onMount fallback 이 처리. 이제 흐름: - 진입 (sessionStorage prefill 만 있음) → onMount await fetch 후 fallback 으로 next_question_number 적용 - dropdown 으로 회차 변경 → onchange={onRoundChange} - 새 회차 입력 → applyNewRound() 안에서 직접 f_qnum=1 - examRounds 변경 (저장 후 refreshExamRounds) → 어떤 자동 reset 도 발생 안 함 --- .../topics/[id]/questions/new/+page.svelte | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/frontend/src/routes/study/topics/[id]/questions/new/+page.svelte b/frontend/src/routes/study/topics/[id]/questions/new/+page.svelte index 9566df2..dec4c7b 100644 --- a/frontend/src/routes/study/topics/[id]/questions/new/+page.svelte +++ b/frontend/src/routes/study/topics/[id]/questions/new/+page.svelte @@ -158,21 +158,27 @@ return Array.from(set); }); - // 회차 변경 감지 → 문항 번호 자동 reset + // PR-7 fix: 회차 변경은 명시적 onchange 핸들러로 처리 (이전 $effect 패턴은 + // examRounds fetch 전에 첫 실행되며 f_qnum=1 로 reset 하는 race 발생). + // 사용자가 dropdown 으로 회차를 바꿀 때 + applyNewRound() 에서만 호출. let lastExamRound = $state(''); - $effect(() => { - if (f_exam_round && f_exam_round !== lastExamRound) { - // 기존 회차면 next_question_number, 아니면 1 - const found = examRounds.find((r) => r.exam_round === f_exam_round); - if (found && found.next_question_number) { - f_qnum = found.next_question_number; - } else if (!found) { - f_qnum = 1; - } + function onRoundChange() { + if (!f_exam_round) return; + if (f_exam_round === lastExamRound) return; + if (examRounds.length === 0) { + // examRounds 미적재 → onMount fallback 이 처리. 현재 호출은 skip. lastExamRound = f_exam_round; - refreshCompleteFlag(); + return; } - }); + const found = examRounds.find((r) => r.exam_round === f_exam_round); + if (found && found.next_question_number) { + f_qnum = found.next_question_number; + } else if (!found) { + f_qnum = 1; + } + lastExamRound = f_exam_round; + refreshCompleteFlag(); + } function refreshCompleteFlag() { const found = examRounds.find((r) => r.exam_round === f_exam_round); @@ -370,7 +376,7 @@ {#if f_exam_round_mode === 'select'}
-