- schema: MathUnit enum (common/prob_stat/calculus/geometry) - User: focusUnits(Json), bojHandle(VarChar32) - ProblemSet: mathUnit optional + unique(year,examType,subjectName,mathUnit) - migration: phase10_math_units_and_ps - scripts: wipe-non-math (dry/apply), kice-import refactor (math only, 30문항을 공통22 + 확통/미적/기하 8씩으로 분할 → 2년×4 = 8 ProblemSet) - parsing strategy/ocr-fix/seed/me/study-logs: 비수학 참조 전면 제거 - data/kice, backend/uploads/problems: 비수학 폴더 삭제 - Plans.md: Phase 10 계획 확정 Phase 10A DoD 통과 — prisma validate/format OK, nest build OK, kice-import dry-run 2년 각 46문항 확인, wipe dry-run 8 set/260 problems 확인.
277 lines
38 KiB
Markdown
277 lines
38 KiB
Markdown
# ReLoop v2 — Plans.md (Phase 7 active)
|
||
|
||
작업 히스토리 (Phase 0~6 완료) 는 `.claude/archive/plans-phase0-6.md` 로 이동. 이 파일은 **현재 활성 Phase 만** 다룬다.
|
||
|
||
## Context
|
||
|
||
- Repo: `/home/erang/reloop-v2` (backend NestJS+Prisma, frontend Next.js 14 + styled-components)
|
||
- Deploy: `reloop.nabomhalang.co.kr` / `reloop-api.nabomhalang.co.kr` (mailu-dev VM PM2, HEAD cc946e4)
|
||
- DB: MariaDB on 10.10.10.146:33006, `reloop_v2`
|
||
- Persona forgetting curve 운영 중, 2nd pass review APPROVE
|
||
|
||
## Phase 7 — KICE 실데이터 + 사용자 문제집 추가 + 12 페이지 재디자인 (styled-components)
|
||
|
||
**목적**: 2025/2026학년도 수능 실제 PDF (mailu-dev `/home/dev/reloop-v2/data/kice/`, 290MB) 를 텍스트 파싱해서 ProblemSet 카탈로그로 import 하고, 사용자가 원하는 문제집을 자기 목록에 추가해 개별 문항을 풀 수 있게 한다. 동시에 사용자 제공 디자인 12종을 styled-components 로 재현해 프론트엔드를 재구축한다. 수식이 많은 수학/과탐은 이미지 crop 필요성 때문에 Phase 8 별도 트랙으로 분리.
|
||
|
||
### 기술 결정 (사용자 확정분)
|
||
|
||
| # | 결정 포인트 | 확정 내용 |
|
||
|---|---|---|
|
||
| D1 | CSS 스택 | **styled-components 유지**. Tailwind 도입 안 함. 디자인 파일의 Tailwind 클래스를 styled-components CSS 로 1:1 변환. 디자인 토큰은 기존 `theme.ts` 에 확장 |
|
||
| D2 | PDF 파싱 방식 | **pdf-parse + 정규식 기반 본문 파싱**. 문제 본문·선택지·정답을 DB 에 저장해 우리 화면 디자인으로 직접 렌더. PDF Viewer 임베드 안 함 |
|
||
| D3 | 과목 범위 (MVP) | **텍스트 과목만**: 국어 / 영어 / 한국사 / 사회탐구(생활과 윤리 1과목). 2025+2026 × 4 = **8 ProblemSet, 약 240 문항**. 수식이 벡터인 수학/과탐은 Phase 8 (별도 이미지 crop 파이프라인) |
|
||
| D4 | 정답률 데이터 | MVP 는 `baseCorrectRate: null` 허용. EBSi 오답률 엑셀 수동 import 는 별도 트랙 |
|
||
| D5 | 사용자 문제집 모델 | **`UserProblemSet` join** (userId, problemSetId, addedAt, archivedAt?). 카탈로그는 공유, 추가는 개인. ProblemSet 전체를 큐에 bulk insert 하지 않고, 사용자가 개별 Problem 을 "풀기" 할 때 StudyLog 생성 |
|
||
|
||
### 평가원 PDF 파싱 — 휴리스틱 설계
|
||
|
||
평가원 기출 PDF 는 포맷이 매우 일관적이라 LLM 없이 정규식 + 룰베이스로 70~90% 파싱 가능. 실패 케이스만 import 스크립트에서 `needs_review=true` flag 로 표시하고 나중에 수동 보정.
|
||
|
||
**문항 분할 규칙**:
|
||
- 문항 시작: `/\n?\s*(\d{1,2})\.\s+/` — 1~45 번
|
||
- 선택지 시작: `/[①②③④⑤]/` — 원문자 5 종
|
||
- 공통 지문: `/\[(\d+)~(\d+)\]/` — "[1~3]" 형식. 해당 범위 문항은 같은 `Passage` FK 공유
|
||
- 정답표 파싱: `/(\d{1,2})번?\s*[①②③④⑤1-5]/` 또는 표 구조 raw text
|
||
|
||
**Problem 모델 확장**:
|
||
- `bodyText Text` — 문제 본문 (선택지 제외)
|
||
- `choices Json` — `{"1":"...","2":"...","3":"...","4":"...","5":"..."}`
|
||
- `answerNumber Int?` — 1~5
|
||
- `passageId Int?` — 공통 지문 FK (별도 `Passage` 테이블)
|
||
- `needsReview Boolean @default(false)` — 파싱 엣지케이스 표시
|
||
|
||
### Phase 7A — KICE 데이터 파이프라인 (텍스트 파싱)
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
| 7A.1 | Prisma 스키마 확장: `ProblemSet` 에 `audioUrls Json?`. `Problem` 에 `bodyText String? @db.Text`, `choices Json?`, `answerNumber Int?`, `passageId Int?`, `needsReview Boolean @default(false)`. 새 모델 `Passage` (공통 지문). examRound 는 기존 examType 과 중복이라 제외 | `prisma migrate dev --name kice_text_fields` 성공, `@prisma/client` 재생성 | - | cc:완료 [e2e3e4b] |
|
||
| 7A.2 | `backend/scripts/kice-import.ts` 스캐너 — `data/kice/{year}/{과목}/*.pdf` 순회, `생활과 윤리` 특수 경로 처리, 영어 mp3 수집, dry-run 출력 | `pnpm cli:kice-import --dry-run` 이 2025/2026 전체 파일을 tree 로 출력 | 7A.1 | cc:완료 [35dcf82] |
|
||
| 7A.3 | **정답표 파서**: `pdftotext -layout` + 홀/짝 분리 + `/(\d{1,2})\s*[①②③④⑤]/` + 원문자→1..5 정규화. 2025 는 이미지 PDF 라 0 bytes → answerNumber null + needsReview | 2026 4과목 정답 추출 완료, 2025 는 OCR 필요 flag | 7A.2 | cc:완료 [35dcf82] |
|
||
| 7A.4 | **문제지 파서 — 본문 분할**: `pdftotext -raw` (2단 컬럼 physical order), `/^\d{1,2}\.\s+/` monotonic 체크, ①..⑤ 위치로 본문/선택지 분할 | 2026 4과목 각 45문항 전부 본문+5 선택지 분리 | 7A.2 | cc:완료 [35dcf82] |
|
||
| 7A.5 | **공통 지문 파서**: `/\[\s*(\d+)\s*[~~-]\s*(\d+)\s*\]/` 감지 → Passage 레코드 생성 → 범위 내 Problem 에 passageId FK 부착 | 2026 국어/영어에서 26개 passage 생성, 각 Passage 에 2+문항 연결 | 7A.4 | cc:완료 [35dcf82] |
|
||
| 7A.6 | **파싱 실패 가드**: bodyText <10 chars, choices!=5, 빈 choice → needsReview=true | 2026 영어 5 needsReview (듣기 문항), 2025 전체 130 needsReview (OCR 대상) | 7A.4, 7A.5 | cc:완료 [35dcf82] |
|
||
| 7A.7 | **ProblemSet + Problem upsert**: (year, examType, subjectName) upsert, Passage delete+recreate, Problem upsert (problemSetId_number), audioUrls 영어만 | 로컬 DB: 9 ProblemSet / 260 Problem / 26 Passage, 재실행 멱등성 확인 | 7A.3, 7A.6 | cc:완료 [35dcf82] |
|
||
| 7A.8 | `seed.ts` 의 DEMO_PROBLEMSET(2024 수학) 블록 제거 + 2024 수학 ProblemSet DB DELETE + seed 재실행 검증 | seed.ts DEMO_PROBLEMSET 0건, seed 재실행 에러 없음, ProblemSet.count() 는 kice import 만 | 7A.7 | cc:완료 [35dcf82] |
|
||
|
||
**제외** (Phase 8 별도 트랙): 수학·과탐·직업탐구·제2외국어 — 수식/도표 비율 높아서 텍스트 파싱 부적합. 이미지 crop 또는 Vision API 파이프라인이 필요해 Phase 7 에 포함하지 않음.
|
||
|
||
### Phase 7B — 사용자 문제집 추가 플로우
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
| 7B.1 | Prisma: `UserProblemSet` 모델 (`userId`, `problemSetId`, `addedAt`, `archivedAt DateTime?`, `@@unique([userId, problemSetId])`, `@@index([userId])`) | migration 통과, User/ProblemSet 양방향 relation 정의됨 | 7A.1 | cc:TODO |
|
||
| 7B.2 | backend `me/problem-sets` module: `GET /api/me/problem-sets` (내 추가분 list), `POST /api/me/problem-sets` (`{ problemSetId }`), `DELETE /api/me/problem-sets/:id` (soft archive) | 데모 계정으로 3개 API 모두 200/201/204 응답. 중복 추가 시 409 | 7B.1 | cc:TODO |
|
||
| 7B.3 | frontend `lib/api.ts` 에 `UserProblemSet`, `addProblemSet`, `listMyProblemSets`, `removeProblemSet` 타입/헬퍼 추가 | 타입 에러 없이 컴파일, stats 페이지에서 호출 가능 | 7B.2 | cc:TODO |
|
||
| 7B.4 | frontend `/study` 페이지 탭 재설계: [내 문제집 / 카탈로그 / 직접 입력] 3 탭. "카탈로그" 에 전체 ProblemSet 목록 + 각 카드에 "+ 내 목록에 추가" 버튼. "내 문제집" 에 추가한 것만 표시 | 카탈로그에서 카드 클릭 → 내 목록 탭에 즉시 반영. 중복 클릭 방지 | 7B.3 | cc:TODO |
|
||
| 7B.5 | "내 문제집" 탭 상세: 선택한 ProblemSet → 문항 리스트 → 각 문항 "풀기" 버튼 → 기존 `/study/form?problemId=N` 으로 이동해 결과 입력 | 데모 계정에서 2026 수학 → 15번 클릭 → 결과 기록 → 복습 큐 진입까지 전 플로우 통과 | 7B.4 | cc:TODO |
|
||
|
||
### Phase 7C — 디자인 토큰 확장 + styled-components primitives 증축
|
||
|
||
기존 `theme.ts` + `primitives.tsx` 를 유지하고 디자인 파일의 토큰/컴포넌트만 이식한다. Tailwind 도입 없음.
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
| 7C.1 | `frontend/src/styles/theme.ts` 확장 — 새 컬러 (bgDeep `#0F0F14`, surfaceDeep `#15151C`, surfaceHover `#1A1A24`, borderSoftAlpha `rgba(255,255,255,0.06)`, brandGradient 함수), shadow (glowIndigo/glowViolet/cardElevated), keyframes(fadeInUp/float/slideToast/shimmer), font.display (Inter) | `theme.color.bgDeep` 등 5+ 신규 토큰 접근 가능, 기존 토큰과 공존 | - | cc:완료 [ba4d6e4] |
|
||
| 7C.2 | Phosphor Icons React 도입 — `pnpm add @phosphor-icons/react`. `components/ui/Icon.tsx` 어댑터 (name 매핑 + size/weight props) | `<Icon name="squares-four" weight="regular" size={20} />` 가 디자인 파일의 `<i class="ph ph-squares-four">` 와 시각적으로 동일 | 7C.1 | cc:완료 [0d2303a] |
|
||
| 7C.3 | Inter + JetBrains Mono 웹폰트 — `next/font/google` 로 Pretendard(유지) 외에 Inter, JetBrains Mono 로딩. `theme.font.display` / `theme.font.mono` 바인딩, FOUT 없음 | 3종 웹폰트가 production HTML 에 load | 7C.1 | cc:완료 [140a7c3] |
|
||
| 7C.4 | `components/ui/primitives.tsx` 증축 — 새 variants: `Button $variant="white"` (흰색 CTA, 디자인 1의 "지금 시작"), `Card $variant="glow"` (radial glow), `KbdHint` (키보드 단축키 pill), `StatCard` (대형 숫자 카드 레이아웃), `AppShellLayout` | 5+ 신규 export, TypeScript 통과 | 7C.1 | cc:완료 [b9874ad] |
|
||
| 7C.5 | `components/ui/Toast.tsx` 신규 — slideToast 애니메이션, undo 버튼 + 원형 progress ring (2초 타이머). `showToast({ message, onUndo })` 헬퍼 | toast 호출 시 bottom-center 슬라이드 인, 2초 후 자동 dismiss 또는 undo 클릭 시 콜백 | 7C.1, 7C.2 | cc:완료 [eb10dfe] |
|
||
|
||
### Phase 7D — 페이지 재디자인 (12종)
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
참조 디자인 파일: `/home/erang/reloop-v2/.claude/archive/designs/design-NN.html` (Tailwind 기반 mockup, styled-components 로 1:1 이식). **Tailwind 도입하지 않음** — 클래스를 styled-components CSS 로 변환.
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
| 7D.1 | **AppShell (사이드바)** — design-01.html 의 `aside.w-64` 레이아웃 (256px, 다크 bgDeep, indigo radial glow blur-80px, backdrop-blur-xl). 로고 indigo→violet gradient + Phosphor `ph-infinity`, nav 5 항목(대시보드/복습/학습 기록/통계/과목 및 태그) Phosphor icons, 활성 라우트 bg-white/5 + border-white/5, 하단 user card (아바타 + nickname + plan badge + caret 드롭다운). 모바일에서는 BottomNav 로 대체 | 기존 SideNav.tsx 교체, `/dashboard` 진입 시 새 사이드바 렌더, 활성 라우트 강조, 로그아웃 클릭 동작 | 7C.5 | cc:완료 [d35fc08] |
|
||
| 7D.2 | **Landing (`/`)** — design-02.html 1:1 이식. nav + hero "잊기 직전에 딱 한 번 더" + screenshot mockup + features 3카드 + how-it-works 4단계 + stats 카운터 + pricing teaser + FAQ + footer. SSR/하이드레이션 (로그인 상태면 `/dashboard` 리다이렉트는 middleware 쿠키) | 로그아웃 상태에서 `/` 200, 모든 섹션 렌더, 로그인 사용자는 `/dashboard` 리다이렉트 | 7C.5 | cc:완료 [0605ba8] |
|
||
| 7D.3 | **Auth (`/login` + `/register`)** — design-04.html 이식. 단일 카드 UI, 로그인/회원가입 탭 토글, 이메일/비번/닉네임 필드, 에러 shake 애니메이션, "로그인 없이 체험하기" = 데모 계정 자동 로그인 | 두 경로 모두 같은 컴포넌트 사용 (URL path 로 초기 탭 결정), 기존 auth flow 유지 + 에러 UI | 7C.5 | cc:완료 [750378c] |
|
||
| 7D.4 | **Pricing (`/pricing`)** — design-03.html 이식. 월/연 토글, Free/Pro(가장 인기)/School 3 카드, "모든 플랜 공통 4 기능", 상세 기능 비교 테이블(3 섹션 구조), FAQ 4개, 바닥 CTA | 토글 동작 시 가격 숫자 전환, 테이블 모바일 숨김, FAQ 아코디언 | 7C.5 | cc:완료 [92e054c] |
|
||
| 7D.5 | **Dashboard filled (`/dashboard`)** — design-01.html 우측 main 영역 이식. 헤더 (오늘 N개 복습 대기 + streak 뱃지 `ph-fill ph-fire`), 3 통계 카드 (오늘 큐 / 주간 정답률 + sparkline / 마스터리 원형 SVG 34%), "곧 내 것이 되는 영역" 리스트, "최근 학습" 리스트, 적응형 학습 코치 배너. 실제 API (/dashboard/summary) 연동 | 데모 계정 로그인 후 `/dashboard` 에서 실데이터 렌더, 마스터리 원형 SVG + streak 숫자 정확 | 7D.1 | cc:완료 [eeb772a] |
|
||
| 7D.6 | **Dashboard empty (`/dashboard`)** — design-08.html 이식. Welcome + 3단계 체크리스트. 조건: `subjects.length === 0 && studyLogs.length === 0` 에 자동 전환 | 신규 계정 (/register 직후) 은 empty 상태 렌더, 과목 1개 이상 생기면 filled 로 | 7D.5 | cc:완료 [e79c4d8] |
|
||
| 7D.7 | **Review 세션 (`/review`)** — design-05.html 이식. 집중 모드 헤더 (뒤로 + ReLoop 로고 + 집중 모드 뱃지), Day N 제목 + 진행률 바 + 키보드 힌트, 카드 스택 (3 layer stacked), 과목 뱃지 + 회차 + 예측 P%, 메모 블록, 4 액션 버튼 (틀림/부분/맞음/스킵) 색상별, Toast "결과 기록됨 + undo 2s" | 2026 큐에서 카드 전체 처리 + undo 동작 + 단축키 1/2/3/S | 7D.1 | cc:완료 [fdc3e4f] |
|
||
| 7D.8 | **Study History (`/study/history`)** — design-10.html 5 컬럼 테이블 (항목/과목·태그/날짜·시간/결과/자신감) 이식. 검색 + 과목 필터 + 날짜 필터 + 결과 탭. 페이지네이션 (20건/페이지). design-12.html 는 참고용 대안 | `/api/study-logs` 전체 목록이 테이블 렌더, 필터 동작, 빈 상태 UI | 7D.1 | cc:완료 [46c6a45] |
|
||
| 7D.9 | **Subjects & Tags (`/subjects`)** — design-07.html 이식. 상단 tabs (전체/과목별), 과목 섹션 카드 (색상 dot + 이름 + 마스터리 %), 각 섹션 안에 태그 리스트 (P-value + bar + 수정/보관 액션) | /subjects 에서 실제 데이터 렌더, 태그 편집 인라인, 보관 soft archive 동작 | 7D.1 | cc:완료 [0850507] |
|
||
| 7D.10 | **Stats (`/stats`)** — design-11.html 이식. 학습 히트맵 (주×월 grid) + 과목별 정답률 bar 리스트 + 마스터리 P-value 성장 곡선 (SVG path). 기존 `/api/stats/*` + `/api/stats/mastery-path` 활용. design-06.html 는 참고용 대안 | 3 패널 전부 실데이터 렌더, 곡선 mastery-path 응답 기반 | 7D.1 | cc:완료 [0e61f0e] |
|
||
| 7D.11 | **Settings/Profile (`/profile`)** — design-09.html 이식. 계정 + Pro plan 카드, 학습 목표 슬라이더, 알고리즘 민감도 3 카드, 3 toggle 알림, 연속 학습 달력 (7 열 heatmap), 데이터 export / 진행 초기화 / 로그아웃 | 모든 설정이 `/me/profile` PATCH 와 연동, 변경사항 저장 시 즉시 반영 | 7D.1 | cc:완료 [22f3be2] |
|
||
| 7D.12 | **Study 폼 (`/study`)** — 디자인 제외 영역. 기존 기능 유지 + Phase 7B 의 "내 문제집" 탭 추가는 7B 에서. 이 태스크는 기존 탭들을 새 theme/primitives 로 시각적 통일만 | 기존 플로우 유지, 새 theme 컬러/폰트 적용 | 7C.5 | cc:완료 [22ee6ab] |
|
||
|
||
### Phase 7F — 7D 피드백 리비전 (용어 순화 + 모의고사 + 모바일)
|
||
|
||
사용자 피드백 3건을 정리한다.
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
| 7F.1 | **수학 용어 순화** — UI 전반에서 `P`, `P-value`, `P=0.85`, `P ≥ 0.9` 같은 수학 표기를 제거하고 "예상 정답률", "숙련도", "마스터 기준(90%)" 같은 자연어로 교체. 변경 대상: dashboard/stats/review/subjects/profile/dashboard-empty 등 모든 UI 텍스트. 내부 변수명/API 필드는 유지, **화면에 표시되는 문자열만** 변경 | 모든 페이지에서 "P=" / "P-value" / "P ≥" 리터럴 0건, 의미 동등한 자연어로 대체 | 7D.12 | cc:완료 [cbc3af2] |
|
||
| 7F.2 | **모의고사 학습 플로우** — `/study` 의 "새 학습 기록" 화면에 "문제집에서 풀기" 탭 추가. 탭에서 Phase 7A 로 import 된 KICE ProblemSet 을 선택 → 모의고사 인터페이스 (시험지 느낌의 문제 네비게이션, 카운트다운 타이머, 1-5 선택지 버튼, 표시/건너뛰기, 답안지 확인 모드, 제출 후 각 문항 자동 채점 + StudyLog 일괄 생성). 과목별 실제 시험 시간 매핑 (국어 80분/영어 70분/한국사·탐구 30분) | 데모 계정으로 2026 국어 선택 → 타이머 동작 → 문항 번호 클릭 네비 → 답 체크 → 제출 → 각 Problem 당 StudyLog row 생성 + /dashboard 의 "최근 학습" 에 즉시 반영 | 7A.7, 7D.12 | cc:완료 [31d62fb] |
|
||
| 7F.4 | **파서 리팩토링 + segmentation 수정** — `backend/scripts/kice-import.ts` 의 파싱 로직을 `backend/src/problem-sets/parsing/` 모듈로 추출 (범용 설계, 전략 기반). 페이지 헤더/푸터 strip (`제N교시`, `홀수형/짝수형`, `2026학년도 대학수학능력시험 문제지 N`, 페이지 번호, 저작권 문구), 문제 경계 정확도 (다음 `\d{1,2}\.\s+` OR 다음 `[N~M]` OR EOF 중 최소값), passage 헤더 포함 (`[1~3] 다음 글을 읽고…` 를 본문 안에 보존), ⓐⓑⓒⓓⓔ 각주 마커 유지. 재임포트 후 샘플 문항 수동 검증. 향후 업로드 엔드포인트에서 재사용 가능한 순수 함수 시그니처 (buffer 입력) | 2026 국어/영어/한국사/생활과윤리 재임포트 후 needsReview ≤ 5% (듣기 외), 문항 3번 선택지 안에 다른 지문/헤더 오염 0건, passage 첫 줄 "다음 글을 읽고…" 포함 | 7A.7 | cc:완료 [c9935cf] |
|
||
| 7F.5 | **OCR fallback (Vision API)** — 7F.4 이후에도 needsReview 로 남는 엣지케이스 문항만 타겟. `backend/scripts/ocr-fallback.ts` 스크립트가 `pdftoppm` 으로 해당 페이지 crop 렌더 → Claude Vision API 로 구조화 JSON 추출 → Problem 레코드 업데이트. 2025 4과목 답안지 (이미지 PDF) 도 이 경로로 처리 | 2026 4과목 needsReview 0건, 2025 4과목 답안지 OCR 결과로 answerNumber 전부 채움 | 7F.4 | cc:완료 [dcf1eb6] |
|
||
| 7F.3 | **모바일 반응형 스윕** — 12 개 신규 페이지 전부 모바일 브레이크포인트 (`theme.breakpoint.tablet` 이하) 대응. 사이드바 숨김 + BottomNav 노출, 그리드 스택, 테이블 카드 레이아웃 전환, 폰트 크기 축소, 패딩 축소. 특히 /dashboard 3카드 1열, /pricing 3카드 1열, /study/history 테이블 → 카드 리스트, /stats 3패널 1열, /review 카드 스택 풀스크린, /subjects 태그 리스트 간격 축소, 모의고사 (7F.2) 인터페이스 모바일 터치 최적화 | iPhone SE (375×667) 뷰포트에서 12 페이지 전부 가로 스크롤 없음, 주요 버튼 터치 영역 44px+, 모바일에서 사이드바 숨김 확인 | 7F.2 | cc:완료 [80b3e98] |
|
||
|
||
### Phase 7G — 사용자 피드백 리비전
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
| 7G.1 | **IA 재구성 + 모바일 로그아웃** — `/exams` 신규 top-level 라우트로 문제집 카탈로그 분리. SideNav 에 "문제집" 항목 추가, `/study` 폼에서 "문제집에서 풀기" 탭 제거. 시험 페이지 우상단 "집중 모드" 토글 버튼 (ON=풀스크린 / OFF=AppShell 포함). `/login` `/register` 상단 "← 홈으로" 링크. 모바일에서 로그아웃/프로필 접근 (BottomNav 에 프로필 탭 또는 상단 메뉴) | /exams 진입 가능, study 폼 문제집 탭 제거, 집중모드 토글 동작, 로그인에서 홈 이동, 모바일 로그아웃 접근 가능 | 7F.5 | cc:완료 [47a70f2] |
|
||
| 7G.2 | **시험 UX 전면 개선** — 네비 4버튼 (이전/건너뛰기/다음/항목이동) 전부 노출, 시험 종료는 `⋮` 메뉴로. 데스크톱/태블릿 문제 패널 드래그 리사이즈 (localStorage). 모바일 탭 시 확대 모달. 자동 채점 제출 시 Subject+Tag 자동 생성/매칭 보장. Problem.imageUrl 렌더 (7H.1 의존). Subject+Tag 자동 생성 강화: topic 필드 → Tag | 4 버튼 동작, 시험 종료 숨김, 데스크톱 리사이즈, 모바일 확대, 제출 후 과목/태그 자동 생성 확인 | 7G.1 | cc:완료 [7c5cdf4] |
|
||
| 7G.3 | **StudyLog 상세 + 복습 파이프라인 검증** — `/study-logs/[id]` 신규 상세 라우트 (문항 재열람: 본문/선택지/정답/내 답/메모). 대시보드 "최근 학습" + 학습 기록 행 클릭 → 상세 이동. 모의고사 제출 → ReviewSchedule 생성 플로우 검증 + 오늘 복습 큐 진입 확인. 첫 시도 S₀ 시드 조정 (baseCorrectRate 반영) | 문항 상세 재열람, 모의고사 제출 후 24h 내 복습 큐 등장, 초기 복습 간격 난이도 반영 | 7G.2 | cc:완료 [9068fcb] |
|
||
| 7G.4 | **랜딩 리파인 + D-day 동기화 + 애니메이션** — Hero typing effect (3-5개 격려 문구 rotation), 수능 D-day 실시간 계산 (고정 상수 = 2026-11-13, 매일 자동 갱신), 전역 소프트 애니메이션 (카드 hover/scroll fade-in via Intersection Observer), dashboard/review/stats 문구 동기부여 톤 재작성 | Typing effect 동작, D-day 매일 자동 갱신, 스크롤 애니메이션 부드러움, 톤 개선 | 7C.5 | cc:완료 [feb1a62] |
|
||
| 7G.5 | **통계 히트맵 리사이즈 + 테마드 폼 컴포넌트 + 과목 페이지 수정** — 통계 히트맵 50% 축소 + 요일 라벨 + 클릭 시 해당일 드로어. `components/ui/Select.tsx` + `DatePicker.tsx` (다크 테마). /study/history 필터/profile 셀렉터/subjects 정렬 전부 새 컴포넌트로 교체. 과목 페이지 모바일 탭 버튼 세로 글씨 수정 → horizontal scroll pill | 히트맵 축소 + 기능, 모든 드롭다운 다크 테마, 과목 탭 가로 정렬 | 7D.10 | cc:완료 [e332d27] |
|
||
| 7G.6 | **프로필 + 아바타 + 온보딩** — Backend: `User.avatarUrl`, `POST /me/avatar` multipart (`backend/uploads/avatars/`). Frontend `/profile` 아바타 업로드 UI. `/onboarding` 플로우 보강 (현재/목표 등급, 중점 과목, 수능 연도, 페르소나). 신규 가입 후 자동 진입. 프로필 드롭다운 모바일 접근 | 아바타 업로드 + 저장 + URL 반환, 온보딩 완전 동작, 프로필 드롭다운 모바일 접근 가능 | 7G.1 | cc:완료 [a5dab35] |
|
||
|
||
### Phase 7H — 수학 + 이미지 기반 문제 지원
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
| 7H.1 | **수학 데이터 + 스키마 + 이미지 파이프라인** — mailu-dev 에서 2025/2026 수학 PDF rsync. Prisma 확장 `Problem.imageUrl String?`, `Problem.pageImageUrl String?` + migration. `parsing/strategies/math.ts` — pdftoppm 으로 per-problem PNG 렌더. 이미지는 `backend/uploads/problems/{year}/{subject}/{number}.png`. `kice-import --subject=수학` 동작, 답안지 OCR fallback 재사용 | 2025/2026 수학 각 30문제 import 완료, imageUrl 채움, 답안 자동 채점 | 7F.4, 7F.5 | cc:완료 [acc35e9] |
|
||
| 7H.2 | **프론트 이미지 렌더 + 시험 UI 통합** — Problem 타입에 imageUrl 추가. 시험/복습 UI: imageUrl 있으면 `<img>` 메인. 사진/표 포함 문제도 동일 경로. /uploads static 서빙 NestJS | 수학 문항 시험 화면에서 정상 렌더, 이미지 포함 문제 시각 표시 | 7H.1, 7G.2 | cc:완료 [8a91ab4] |
|
||
|
||
### Phase 8 — 판매 준비 (production ready)
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
| 8.1 | **PWA + SEO 메타** — manifest.webmanifest, 앱 아이콘 세트 (192/512 + apple-touch), theme-color, per-route `generateMetadata` 로 OG 태그, robots.txt, sitemap.xml | `/` 설치 배너, OG 미리보기, robots/sitemap 서빙 | 7G.6 | cc:완료 [7ba7b4a] |
|
||
| 8.2 | **법적 페이지 + 404/500 + 에러 바운더리** — `/privacy`, `/terms`, `/contact` 페이지 (footer 링크). `app/not-found.tsx`, `app/error.tsx`, `app/global-error.tsx` 테마드 페이지 | 4 경로 렌더, 404/500 테마드 | 7G.4 | cc:완료 [eb0e07b] |
|
||
| 8.3 | **보안 + rate limit + 환경 하드닝** — helmet 강화, CORS 화이트리스트, @nestjs/throttler 전역 rate limit (분당 60), 데모 계정 평문 비밀번호 stdout 제거, `.env` 템플릿 정리 | 로그인 스팸 60/분 초과 429, seed 평문 노출 0 | 7G.6 | cc:완료 [c36978c] |
|
||
|
||
### Phase 7I — 2차 피드백 리비전 (이미지 우선 + UX)
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
| 7I.1 | **전 과목 per-problem 이미지 crop** — `pdftotext -bbox` 로 문제 번호 Y좌표 추출 → `pdftoppm -x -y -W -H` 으로 문제별 PNG crop → `uploads/problems/{year}/{subject}/{number}.png` 저장. 모든 과목 적용. 텍스트 파싱은 보조, 이미지가 주 표시. 재임포트 후 320 문항 전부 imageUrl 보유 | 2025/2026 × 5과목 재임포트, 320 problems 전부 imageUrl, 수학 포함 정상 | 7H.1 | cc:완료 [e76e14e] |
|
||
| 7I.2 | **chosenAnswer + 개별 풀기 + 프로필 통합** — (a) `StudyLog.chosenAnswer Int?` migration. 제출 시 저장. (b) `/solve/[studyLogId]` 개별 문제 풀기 라우트. (c) `/profile` + `/settings` 통합: 단일 페이지 탭 | chosenAnswer 저장 + detail 표시, 개별 풀기, 프로필 단일 페이지 | 7I.1 | cc:완료 [4c61b87] |
|
||
| 7I.4 | **3차 피드백 일괄** — (a) 집중모드 기본 OFF (review+exam localStorage 기본값 false). (b) /profile 등급 슬라이더 네이티브 HTML → 테마드 커스텀 슬라이더. (c) 문제 표시 이미지 ONLY (텍스트 파싱 제거, 선택지도 이미지). 수학 등 OMR 스타일 1-5 버블 (식 표기 대신). (d) 이미지 가운데 정렬. (e) 국어 지문+문제 세트: passage 이미지 crop 도 생성 + 시험 UI 에서 지문 이미지 먼저 표시. (f) /pricing 연결 (로그인 후 접근). (g) 영어 듣기 오디오 재생기 (mp3 서빙 + `<audio>` UI). (h) / 메인 typing effect 속도 줄임 + 긴 타이틀 overflow 수정 + 전반 애니메이션 속도 감속 | 모든 항목 동작 확인 | 7I.3 | cc:완료 [d14fde3] |
|
||
| 7I.3 | **UI 일괄 수정** — (a) 복습 집중모드 토글. (b) 통계 3패널 재배치. (c) 시험 간격/그림자/긴 지문. (d) SideNav 프로필 고정. (e) 배경 통일 | 복습 토글, 통계 깔끔, 시험 가독성, SideNav 고정, 배경 일관 | 7I.2 | cc:완료 [59f6652] |
|
||
|
||
### Phase 9 — 학교/학원 관리 (School Plan)
|
||
|
||
**목적**: 선생님(관리자)이 학급을 만들고, 학생을 초대하고, 문제집을 과제로 배정하고, 학생별 진도/성적을 추적할 수 있는 기관 관리 기능. Pricing 의 "School" 플랜에 대응.
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
| 9.1 | 스키마 + 백엔드 API (Organization/Class/Assignment) | 엔드포인트 200, seed, migration | 8.3 | cc:완료 [f4b80d3] |
|
||
| 9.2 | 선생님 대시보드 + 학급 + 초대 (9.5 통합) | 대시보드/학급/초대/역할 분기 | 9.1 | cc:완료 [bed5b80] |
|
||
| 9.3 | 과제 CRUD + 제출 현황 UI | 과제 생성→풀기→현황 전 플로우 | 9.2 | cc:완료 [8ebd419] |
|
||
| 9.4 | 학생 진도 + 리포트 (3 차트) | 학생 상세, 학급 리포트 렌더 | 9.3 | cc:완료 [f9c8b9a] |
|
||
|
||
### Phase 10 — KICE 비수학 제거 + Solved.ac PS 통합 + 온보딩 재설계
|
||
|
||
**목적**: 저작권 리스크(비수학 KICE 기출)를 제거하고, 수능 수학 4단원(공통/확통/미적/기하) + Solved.ac 기반 PS 두 가지 학습 트랙만 남긴 구조로 재편한다. 사용자는 온보딩에서 `수학 수능 / PS / 자격증 / 어학 / 취미` 중 목표를 선택하고, `수학 수능` 선택 시 세부 단원을, `PS` 선택 시 solved.ac 핸들을 연결한다. Solved.ac 풀이 이력은 자동 sync 되어 `StudyLog` 로 복습 큐에 진입한다.
|
||
|
||
### 기술 결정 (Phase 10)
|
||
|
||
| # | 결정 포인트 | 확정 내용 |
|
||
|---|---|---|
|
||
| P10-D1 | 수학 단원 모델 | `enum MathUnit { common, prob_stat, calculus, geometry }` — `common` = 수학Ⅰ+Ⅱ, 선택 3종(확률과 통계/미적분/기하). `ProblemSet.mathUnit MathUnit?` 으로 nullable 추가 |
|
||
| P10-D2 | KICE 30문항 단원 분할 | 공통 22문항 (1~22) + 선택 8문항 × 3단원 (23~30 각 세트). 즉 year 당 수학 ProblemSet = 4개(common/prob_stat/calculus/geometry), problems = 22+8+8+8 = 46. 2년치 × 4 = **8 ProblemSet** 총 92 problems |
|
||
| P10-D3 | 비수학 데이터 처리 | Dev DB 에서 `ProblemSet.subjectName NOT IN ('수학')` 에 연결된 Problem/StudyLog/ReviewSchedule/AssignmentSubmission cascade delete. 되돌리기 불가 — 마이그레이션 전 mysqldump 백업 필수 |
|
||
| P10-D4 | Solved.ac 통합 깊이 | **(c) 풀: 검색+북마크 + 핸들 자동 sync**. `SolvedAcClient` 는 `https://solved.ac/api/v3` 공개 API 사용(인증 불필요), `user/show` + `user/problem_stats` + `user/top_100` 조합으로 bulk import |
|
||
| P10-D5 | PS → StudyLog 매핑 | `PsProblem` 별도 테이블에 캐시. `StudyLog.problemId` 는 KICE `Problem` FK 라 재사용 불가 → `StudyLog.psProblemId Int?` 추가. `subject` 는 자동 생성되는 시스템 Subject `"PS"` 로 묶음 |
|
||
| P10-D6 | 온보딩 GoalType | `'math-suneung' \| 'ps' \| 'certificate' \| 'language' \| 'none'`. `User.focusUnits Json?` 추가(수학 단원 멀티셀렉트 저장), `User.bojHandle String?` 추가 |
|
||
| P10-D7 | 기존 focusSubjects | `focusSubjects`는 그대로 유지하되 수학 선택지만 남김. 자격증/어학/취미 트랙은 자유 입력 유지 |
|
||
| P10-D8 | 학교/학원 기능 | Phase 9 Assignment 는 수학 ProblemSet 에 대해서만 작동. 스키마 변경 없음 |
|
||
|
||
### Phase 10A — 스키마 + KICE 비수학 제거
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
| 10A.1 | Prisma 스키마: `MathUnit` enum, `ProblemSet.mathUnit MathUnit?`, `User.bojHandle String? @db.VarChar(32)`, `User.focusUnits Json?`. migration `phase10_math_units_and_ps` 생성 | `prisma migrate dev --name phase10_math_units_and_ps` 성공, `@prisma/client` 재생성, 기존 행 NULL 기본값 | - | cc:TODO |
|
||
| 10A.2 | 비수학 데이터 wipe 스크립트 `backend/scripts/wipe-non-math.ts` — `ProblemSet where subjectName != '수학'` 연쇄 삭제(Assignment/AssignmentSubmission, StudyLog, ReviewSchedule, Problem, Passage 포함). 실행 전 mysqldump 백업을 `backups/` 에 저장 | dry-run 시 삭제 대상 수 출력, `--apply` 시 실제 삭제 후 `ProblemSet count where subjectName='수학'` 만 남음 | 10A.1 | cc:TODO |
|
||
| 10A.3 | `kice-import.ts` 리팩터: `TARGET_SUBJECTS = ['수학']`, 30문항을 1~22 = common, 23~30 = 선택 × 3 단원으로 split 하여 4 ProblemSet 생성. `ProblemSet.title` 은 `YYYY학년도 수능 수학 (공통)` 형태 | `pnpm cli:kice-import --dry-run --year=2026` 시 common 22 + 확통 8 + 미적 8 + 기하 8 = 46 문항 리포트 | 10A.2 | cc:TODO |
|
||
| 10A.4 | `backend/src/problem-sets/parsing/strategies/kice.ts` 및 관련 OCR 프롬프트에서 비수학 분기 제거. `shared.ts`·`ocr-fix.ts`·`seed.ts` 에서 비수학 과목 참조 삭제 | `grep -rE "국어\|영어\|한국사\|생활과 윤리\|사회탐구" backend/src backend/scripts` 결과 0 | 10A.3 | cc:TODO |
|
||
| 10A.5 | `data/kice/{2025,2026}/{국어,영어,한국사,사회탐구}/` 삭제 + `.gitignore` 정리. `backend/uploads/problems/{year}/{비수학 과목}/` 도 삭제 | 디스크에 수학 PDF + 수학 이미지 crop 만 남음 | 10A.4 | cc:TODO |
|
||
|
||
### Phase 10B — Solved.ac PS 모듈
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
| 10B.1 | Prisma: `model PsProblem { id Int, bojId Int @unique, title, level Int, tags Json, acceptedUserCount Int?, averageTries Float?, updatedAt }`, `model PsBookmark { userId, psProblemId, createdAt @@unique([userId,psProblemId]) }`, `StudyLog.psProblemId Int?` FK 추가. migration `phase10_ps_tables` | `prisma migrate dev` 성공, 관계 매핑 검증 | 10A.1 | cc:TODO |
|
||
| 10B.2 | `backend/src/ps/solved-ac.client.ts` — axios 인스턴스(`https://solved.ac/api/v3`, User-Agent 명시, 타임아웃 10s, 지수 백오프 3회). 메서드: `searchProblems(query, page)`, `getProblem(bojId)`, `getUser(handle)`, `getUserSolvedProblems(handle, page)`. 내부 rate-limit (초당 3req) | 단위 테스트: mocked axios 로 4 메서드 응답 파싱 정상 | 10B.1 | cc:TODO |
|
||
| 10B.3 | `PsModule` + `PsService` + `PsController` — endpoints: `GET /api/ps/search?q=&level=&page=`, `GET /api/ps/problems/:bojId`, `POST /api/ps/bookmarks { bojId }`, `DELETE /api/ps/bookmarks/:bojId`, `GET /api/ps/bookmarks`, `POST /api/ps/sync { bojHandle? }` (핸들 없으면 `User.bojHandle` 사용). JWT guard + throttler | Postman/curl 6 endpoint 200, sync 실행 시 PsProblem upsert + 시스템 Subject "PS" 생성 + StudyLog bulk insert, 멱등성 확인(중복 sync 시 같은 BOJ 문제 StudyLog 추가 생성 안 함) | 10B.2 | cc:TODO |
|
||
| 10B.4 | Sync 멱등성 저장소: `PsSyncState { userId @unique, lastSyncedAt, lastSolvedCount }` 추가해 마지막 sync 이후 새로 맞힌 문제만 가져옴. 초기 sync 는 `top_100` 기준 상위 100개로 제한(과도한 StudyLog 폭주 방지) | 1차 sync 후 `PsSyncState.lastSolvedCount` 저장, 2차 sync 는 차분만 insert | 10B.3 | cc:TODO |
|
||
|
||
### Phase 10C — 온보딩/프론트 재구성
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
| 10C.1 | `frontend/src/app/onboarding/page.tsx` — GoalType 옵션 라벨/설명 교체. `math-suneung` 선택 시 4 단원 체크박스 그룹 노출, `ps` 선택 시 `bojHandle` 인풋(정규식 검증 `^[a-zA-Z0-9_-]{3,20}$`) 노출 | 각 GoalType 분기 UI 정상, 저장 후 `/auth/me` 응답에 `focusUnits` 또는 `bojHandle` 반영 | 10B.1 | cc:TODO |
|
||
| 10C.2 | `frontend/src/lib/api.ts` + `MeUser` 타입: `bojHandle`, `focusUnits: MathUnit[]`, `GoalType` 유니언 갱신. `api/me` PATCH payload 확장 | 타입 에러 0, API PATCH 200 | 10C.1 | cc:TODO |
|
||
| 10C.3 | 전역 과목 리스트 정리 — `subjects/page.tsx`, `exams/page.tsx`, `review/page.tsx`, `review/history/page.tsx`, `dashboard`, `school/*` 에서 비수학 하드코딩 참조 제거. `exam/shared.ts::getExamDurationSeconds` → 수학 100분 고정. `SideNav` 에서 국어/영어/한국사 링크 제거 | `grep -rE "국어\|영어\|한국사\|생활과 윤리" frontend/src` = 0 | 10C.2 | cc:TODO |
|
||
| 10C.4 | `frontend/src/app/ps/` 신규 섹션 — `page.tsx`(검색 + 필터 + 북마크 버튼), `bookmarks/page.tsx`(북마크 목록), `sync/page.tsx`(핸들 동기화 버튼 + 상태). BottomNav/SideNav 에 `PS` 진입점 추가 | 4 경로 200 + search/bookmark/sync e2e 수동 검증 통과 | 10C.2 | cc:TODO |
|
||
| 10C.5 | `landing`/`pricing`/`dashboard` 카피 업데이트 — "수능 국어/영어…" 문구를 "수학 수능 + PS" 로 교체, 아카이브 design HTML 과 docs 에서도 혼동 없도록 정리 | `grep -rE "국어\|영어\|한국사\|생활과 윤리" frontend/src docs README.md` = 0 (아카이브 `.claude/archive/` 는 제외) | 10C.3 | cc:TODO |
|
||
|
||
### Phase 10D — Dev 배포 + 검증
|
||
|
||
| Task | 내용 | DoD | Depends | Status |
|
||
|------|------|-----|---------|--------|
|
||
| 10D.1 | 로컬 커밋 + push → Gitea `hanarang/reloop-v2 master`. commit 단위는 10A / 10B / 10C 별로 나눔 | `git push` 성공, `tea pr list` 없이 master 직접 반영 | 10C.5 | cc:TODO |
|
||
| 10D.2 | `ssh dev@10.10.10.169` → `cd ~/reloop-v2 && git pull`. backend 에서 `mysqldump reloop_v2 > backups/phase10-pre.sql` 실행 후 `pnpm --filter backend exec prisma migrate deploy` → `pnpm --filter backend build` | 마이그레이션 적용됨, dist/main.js 빌드 성공, DB 백업 존재 | 10D.1 | cc:TODO |
|
||
| 10D.3 | 비수학 wipe 스크립트 운영 실행 — `node backend/dist/scripts/wipe-non-math.js --apply`. 이어서 `pnpm cli:kice-import --year=2025 && --year=2026` 로 수학 8 ProblemSet 재생성 | DB 에 수학 8 ProblemSet / 92 problems, 비수학 0 | 10D.2 | cc:TODO |
|
||
| 10D.4 | Frontend 빌드 + standalone copy + `pm2 reload reloop-web reloop-api --update-env` | PM2 status online, `curl https://reloop-api.nabomhalang.co.kr/health` 200, `curl https://reloop.nabomhalang.co.kr` 200 | 10D.3 | cc:TODO |
|
||
| 10D.5 | 스모크 테스트 — 온보딩 `math-suneung` 플로우 + 단원 선택 저장, `ps` 플로우 + 더미 BOJ 핸들 sync, `/ps/search` 검색, `/exams` 에 수학 4단원 표시, `/review` 에 비수학 흔적 없음 | 5 시나리오 수동 통과 스크린샷 또는 로그 캡처 | 10D.4 | cc:TODO |
|
||
|
||
### Phase 10 범위 / 비 범위
|
||
|
||
**포함**:
|
||
- KICE 비수학 과목(국어/영어/한국사/생활과 윤리) 코드·데이터·DB 전량 제거
|
||
- 수학 4단원 분할(common/prob_stat/calculus/geometry) + 재import
|
||
- Solved.ac 기반 PS 모듈 (검색/북마크/핸들 자동 sync → StudyLog)
|
||
- 온보딩 재설계 (`math-suneung` 세부 단원 / `ps` bojHandle)
|
||
- Dev 배포 + DB 백업/마이그레이션/스모크
|
||
|
||
**제외** (별도 트랙):
|
||
- Solved.ac 인증 API(로그인 연동) — 공개 API 로 충분
|
||
- PS 문제 로컬 렌더링 — BOJ 링크 아웃바운드 유지
|
||
- 수학 30문항 → 단원 분할 비율 조정(정밀 매핑표 필요 시 별도 Phase)
|
||
- 기존 사용자 데이터 마이그레이션 보전(비수학 StudyLog 는 cascade delete)
|
||
- i18n / 영어 UI / PWA
|
||
- 이 Phase 에서는 새 UI 디자인 토큰 변경 없음
|
||
|
||
### 실행 모드
|
||
|
||
- 전량 `harness-work --codex` 위임, Lead 세션이 codex helper 를 통해 Task 단위로 구현/검증
|
||
- 배포(10D)는 ssh + PM2 수동 단계 포함 → Lead 세션이 Bash 로 직접 실행
|
||
- DB 파괴적 작업(10A.2, 10D.3) 실행 전 mysqldump 백업 필수
|
||
|
||
|
||
### 범위 / 비 범위
|
||
|
||
**포함**:
|
||
- KICE 2025/2026 × 5 과목 = 10 ProblemSet import
|
||
- UserProblemSet 추가/조회/보관 API + UI
|
||
- Tailwind 도입 + 디자인 토큰 이식
|
||
- 12 페이지 재디자인 (AppShell 포함)
|
||
|
||
**제외** (Phase 8 이후):
|
||
- 2025/2026 탐구 전 과목 (46+46) 전체 import — 먼저 5과목 패턴 확립 후 Phase 8 자동 확장
|
||
- 정답률/등급컷 데이터 수동 입력 — EBSi 엑셀 별도 트랙
|
||
- 실제 결제 연동 (PortOne/Toss)
|
||
- Pro tier 실제 gating 강제 (P6-F5 TODO 주석 유지)
|
||
- 문제지 PDF 이미지/수식 OCR
|
||
- PWA manifest / offline 지원
|
||
- 학교 Pro 전용 기능 (선생님 대시보드)
|
||
|
||
### 실행 모드 제안
|
||
|
||
전체 35+ 태스크 → **Breezing** 자동 선택되지만 Phase 별로 나눠 순차 실행:
|
||
1. 먼저 **Phase 7C** (Tailwind 도입) — 5 태스크, 다른 Phase 의 전제
|
||
2. **Phase 7A** (KICE 파이프라인) — 7 태스크, backend 중심
|
||
3. **Phase 7B** (UserProblemSet) — 5 태스크, backend + 최소 frontend
|
||
4. **Phase 7D** (12 페이지 재디자인) — 12 태스크, 가장 무거움. 서브 Phase 로 더 쪼개 가능
|
||
5. **Phase 7E** (배포+감사) — 3 태스크
|
||
|
||
**사용자 컨펌 대기 항목**:
|
||
- D1 ~ D5 기술 결정 승인
|
||
- Phase 7D 재디자인을 하나의 세션에서 12개 전부 할지, 서브 Phase (7D-a 사이드바+dashboard / 7D-b auth+landing+pricing / 7D-c review+study+history / 7D-d subjects+stats+profile) 로 쪼갤지
|
||
|
||
## Execution
|
||
|
||
Mode: **Breezing (명시 플래그 --breezing) — 2 Wave**
|
||
Wave 1: 6개 QA 병렬 Worker (정적 분석)
|
||
Wave 2: 5개 fix Cluster 병렬 Worker + Lead 리뷰 + Cluster별 commit
|
||
Lead: 본 세션 (claude-opus-4-6[1m])
|
||
Workers: `claude-code-harness:task-worker` (Wave 2, write 권한)
|
||
AI Residuals: clean (TODO/FIXME/Claude/ChatGPT/Copilot 어느 것도 소스 없음)
|