feat(frontend): 오답노트 복습 드릴 + 연습 답변 유실 수정 (A-7) - #179
Merged
Conversation
## 드릴 상태 기계 추출 (#178 에서 미뤘던 것) `usePracticeSession` 안에 섞여 있던 "한 문제씩 넘기며 답을 적고 정답을 확인하는" 상태를 `useQuestionRunner(questionIds, storageKey?)` 로 뽑았다. 질문 id 목록만 받고 질문을 어디서 얻는지는 모른다. **`shared/hooks` 에 뒀다.** 처음엔 `features/practice` 에 두고 오답노트에서 가져다 썼는데, features 끼리 import 는 FSD 위반이다(§3). 도메인 타입에 의존하지 않으므로 shared 가 맞다. `PracticeRunner` 는 손대지 않았다 — 정적 질문 은행을 쓰는 전체 화면 레이아웃 그대로고, 내부 상태만 공용 훅으로 바뀌었다. ## A-7 — 연습 모드 답변이 새로고침하면 사라지던 문제 `storageKey` 를 주면 답변 메모를 localStorage 에 남긴다. 사용자가 직접 쓴 것이라 잃으면 손실이 크다(질문 목록은 다시 뽑으면 그만). 트랙별로 키를 나눈다. - 저장 실패(용량 초과·프라이빗 모드)는 무시한다 — 드릴이 멈추면 안 된다 - 읽을 때 형식을 검사한다. 다른 코드가 같은 키를 썼거나 형식이 바뀌어도 빈 상태로 시작할 뿐 `reset()` 에서 `removeItem` 을 호출했다가 걷어냈다 — answers 변경으로 저장 이펙트가 곧바로 `"{}"` 를 다시 써서 무의미했다(테스트가 잡았다). 저장은 이펙트 하나가 책임진다. ## 오답노트 복습 드릴 목록 위 '복습 시작' 으로 진입. 한 문제씩 다시 답해 본 뒤 **정답 확인**을 눌러야 그때 내 답변· 모범 답안·코칭이 보인다. 여기 적는 답도 localStorage 에 남는다. 기록이 없는 질문(답변 전에 담았거나 피드백 전)도 드릴에 포함하고, 펼쳤을 때 이유를 알려준다. ## 테스트 - `useQuestionRunner.test.ts` 신설 (7) — 순서·마지막·완료, 다음 질문에서 정답 재차단, **저장/복원**, storageKey 없으면 미저장, reset, **망가진 저장값 방어 3종**, 질문 목록이 짧아질 때 범위 접힘(오답노트에서 항목을 빼는 경우) - `BookmarkDrill.test.tsx` 신설 (6) — 정답 확인 전 미노출, 다음 질문에서 재차단, 기록 없는 질문 안내, 완료 화면, 나가기, 재진입 후 답변 유지 vitest 111/111 · eslint 0 · tsc · build 통과.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
변경 사항
지난 PR(#178)에서 미뤄둔 드릴 추출과 감사 백로그 A-7을 함께 정리했다. 둘 다 같은 코드(연습 러너)를 건드려서 한 묶음으로 갔다.
1. 드릴 상태 기계 추출
usePracticeSession안에 섞여 있던 "한 문제씩 넘기며 답을 적고 정답을 확인하는" 상태를useQuestionRunner(questionIds, storageKey?)로 뽑았다. 질문 id 목록만 받고 질문을 어디서 얻는지는 모른다.shared/hooks에 뒀다. 처음엔features/practice에 두고 오답노트에서 가져다 썼는데, features 끼리 import 는 FSD 위반이다(frontend/src/features/CLAUDE.md §3). 도메인 타입에 의존하지 않으므로 shared 가 맞는 자리다.PracticeRunner컴포넌트는 손대지 않았다 — 정적 질문 은행을 쓰는 전체 화면 레이아웃 그대로고, 내부 상태만 공용 훅으로 바뀌었다. #178 에서 "이 리팩터를 섞으면 연습 모드까지 회귀 위험"이라고 적었던 부분이라, 이번엔 훅만 갈라내고 표현은 건드리지 않는 선으로 제한했다.2. A-7 — 연습 모드 답변이 새로고침하면 사라지던 문제
storageKey를 주면 답변 메모를 localStorage 에 남긴다. 사용자가 직접 쓴 것이라 잃으면 손실이 크다(질문 목록은 다시 뽑으면 그만). 트랙별로 키를 나눈다.reset()에서removeItem을 호출했다가 걷어냈다. answers 변경으로 저장 이펙트가 곧바로"{}"를 다시 써서 무의미한 코드였다 — 테스트가 잡았다. 저장은 이펙트 하나가 단독으로 책임진다.3. 오답노트 복습 드릴
목록 위 '복습 시작' 으로 진입. 한 문제씩 다시 답해 본 뒤 정답 확인을 눌러야 그때 내 답변·모범 답안·코칭이 보인다. 여기 적는 답도 localStorage 에 남는다.
기록이 없는 질문(답변 전에 담았거나 피드백 생성 전)도 드릴에 포함하고, 펼쳤을 때 이유를 알려준다.
테스트
useQuestionRunner.test.ts신설 (7) — 순서·마지막·완료, 다음 질문에서 정답 재차단, 저장/복원, storageKey 없으면 미저장, reset, 망가진 저장값 방어 3종(non-JSON / 배열 / 문자열 아닌 값 섞임), 질문 목록이 짧아질 때 범위 접힘BookmarkDrill.test.tsx신설 (6) — 정답 확인 전 미노출, 다음 질문에서 재차단, 기록 없는 질문 안내, 완료 화면, 나가기, 재진입 후 답변 유지vitest 111/111 · eslint 0 · tsc · build 통과.
영향 범위
stackup:practice-answers:{track},stackup:bookmark-drill-answers리뷰어 체크포인트
Math.min). 이펙트로 되돌리면 한 프레임 깜빡이고react-hooks/set-state-in-effect에도 걸린다