# ReLoop v2 **잊기 전에 다시 만나는 학습법.** 에빙하우스 망각곡선 + SM-2 알고리즘으로 개인화된 복습 간격을 자동 계산하는 학습 플랫폼. > 운영 서버: https://reloop.nabomhalang.co.kr ## 핵심 기능 | 기능 | 설명 | |------|------| | **적응형 복습 스케줄링** | 4가지 학습자 페르소나 + 3단계 자기평가로 최적의 복습 시점을 자동 계산 | | **복습 캘린더 + Quick Add** | 월간 달력에서 날짜별 복습 현황 확인, "+" 버튼으로 바로 학습 기록 등록 | | **3종 문제집** | B2B 프리미엄 ebook, PDF 자동 변환 문제집, 샘플 문제집 12권 | | **PDF 문제 분리** | 모의고사 PDF + 해설지 업로드 → 30초 만에 디지털 문제집 생성 | | **모의고사 모드** | 사용자 설정 타이머 + OMR 답안 선택 + 자동 채점 + 집중 모드 | | **3단계 자기평가** | 어려움/보통/쉬움 → SM-2 기반 간격 배정 | | **필기모드** | Canvas 오버레이, 펜 3색, 문제별 localStorage 저장 | | **B2B QR 등록** | 종이 문제집 QR 코드 → 앱 ebook 자동 등록 | | **학교/학원 관리** | 학급 생성, 일괄/개인 과제, 복습 과제, 풀이 상세 확인, 선생님 해설 공유 | | **2022 교육과정 프리셋** | 중1~고3 과목 생성 시 단원 자동 배치 | | **마스터리 경로** | 단원별 예상 정답률 + 마스터까지 남은 일수 예측 | | **Freemium 구독** | Free(과목 3개, 복습 10개) / Pro(월 2,900원) / School(학생당 월 2,900원) | ## 알고리즘 ReLoop은 두 가지 복습 경로를 제공합니다. 상세 설명은 [ALGORITHM.md](./ALGORITHM.md) 참조. ### 1. SM-2 하이브리드 (메인) 사용자가 "어려웠어/괜찮았어/쉬웠어"를 선택하면 SM-2 알고리즘이 적용됩니다. - **어려웠어** → 1일 후 재복습, EF -0.3 - **괜찮았어** → 기본 간격 × 페르소나 배율 - **쉬웠어** → 간격 확대, EF +0.15 - 간격에 페르소나 배율 + 학습 강도 배율이 곱해짐 (최대 60일 cap) - 망각곡선 안전장치: SM-2 간격 후 예상 P < 30%이면 자동 축소 ### 2. 에빙하우스 망각곡선 (Legacy) ``` S(t) = S₀ × exp(-λ × t) 기억 감쇄 P = sigmoid(k × (S(t) - D)) 정답 확률 ``` | 페르소나 | λ (망각속도) | 간격 배율 | |---------|-------------|----------| | 상위권 (senior) | 0.1 | ×1.3 | | 중위권 (mid) | 0.2 | ×1.0 | | 하위권 (junior) | 0.4 | ×0.8 | | 벼락치기형 (crammer) | 0.6 | ×0.6 | ## 수익 모델 | | Free | Pro | School | |--|------|-----|--------| | 가격 | 0원 | 월 2,900원 / 연 24,900원 | 학생당 월 2,900원 | | 복습 큐 | 일일 10개 | 무제한 | 무제한 | | 과목 | 3개 | 무제한 | 무제한 | | PDF 업로드 | 월 1회 | 무제한 | 무제한 | | 기출 문제집 | 샘플만 | 전체 | 전체 | | 마스터리 경로 | 미리보기 | 전체 | 전체 | | 학교/학원 관리 | - | - | 전체 | ## 기술 스택 | 영역 | 기술 | |------|------| | Backend | NestJS 10, Prisma 5, MariaDB | | Frontend | Next.js 14 (App Router), React 18, styled-components 6 | | 인증 | JWT (passport-jwt) | | 차트 | Recharts | | 아이콘 | Phosphor React | | 폰트 | Pretendard + Inter + JetBrains Mono | | PDF 파싱 | poppler-utils (pdftotext, pdftoppm, pdfinfo) | | 배포 | PM2, nginx reverse proxy | ## 프로젝트 구조 ``` reloop-v2/ ├── backend/ │ └── src/ │ ├── auth/ # JWT 인증 │ ├── dashboard/ # 대시보드 요약 │ ├── forget/ # 망각곡선 + SM-2 엔진 │ ├── me/ # 프로필 + 티어 전환 │ ├── problem-sets/ # 문제집 + PDF 파싱 │ │ └── parsing/ # pdftotext 기반 파서 + OCR fallback │ ├── reviews/ # 복습 큐 (자동 이월 + Free 10개 제한) │ ├── stats/ # 통계 + 마스터리 경로 (Pro 전용) │ ├── study-logs/ # 학습 기록 + PDF 문제 분리 │ ├── subjects/ # 과목 + 교육과정 프리셋 + Free 3개 제한 │ ├── tags/ # 태그 (CRUD + 이름 변경) │ ├── organizations/ # 학교/학원 │ ├── classes/ # 학급 │ └── assignments/ # 과제 (일괄/개인/복습 + 풀이상세 + 선생님 노트) ├── frontend/ │ └── src/ │ ├── app/ │ │ ├── dashboard/ # 대시보드 (캘린더, 숙련도) │ │ ├── review/ # 복습 세션 (키보드 단축키) │ │ ├── exams/ # 문제집 카탈로그 (프리미엄/내 문제집/샘플) │ │ ├── study/ │ │ │ ├── exam/ # 모의고사 화면 (타이머 + 집중모드) │ │ │ ├── import-pdf/# PDF 문제 분리 │ │ │ └── history/ # 학습 기록 │ │ ├── subjects/ # 과목/태그 관리 + 색상 피커 │ │ ├── pricing/ # 요금제 (Free/Pro/School) │ │ ├── profile/ # 프로필 + 학습설정 + 티어 전환 │ │ └── school/ # 학교 관리 │ ├── components/ │ │ ├── ui/ # 공통 UI 컴포넌트 │ │ ├── layout/ # AppShell, SideNav, BottomNav │ │ ├── review/ # ReviewCalendar + Quick Add │ │ └── charts/ # 망각곡선, 숙련도 차트 │ └── lib/ # API 클라이언트, 상수, 인증 └── prisma/ └── schema.prisma # DB 스키마 (15 모델) ``` ## 규모 | 항목 | 수치 | |------|------| | 프로덕션 코드 | 45,641줄 | | API 엔드포인트 | 71개 | | DB 모델 | 15개 | | 프론트엔드 페이지 | 26개 | | 샘플 문제집 | 12권 | ## 빠른 시작 ### 필수 조건 - Node.js 20+, pnpm 9+ - MariaDB/MySQL 8+ - poppler-utils (`apt install poppler-utils`) ### 설치 ```bash git clone ssh://git@your-gitea:2222/hanarang/reloop-v2.git cd reloop-v2 # 백엔드 cd backend pnpm install cp .env.example .env # DATABASE_URL, JWT_SECRET 편집 pnpm prisma migrate dev pnpm prisma:seed pnpm dev # :3001 # 프론트엔드 cd ../frontend pnpm install cp .env.example .env.local # NEXT_PUBLIC_API_URL 편집 pnpm dev # :3000 ``` ### 환경 변수 **Backend** (`backend/.env`) | 변수 | 필수 | 설명 | |------|------|------| | `DATABASE_URL` | O | `mysql://user:pass@host:3306/reloop_v2` | | `JWT_SECRET` | O | 32자+ 랜덤 문자열 | | `JWT_EXPIRES_IN` | - | 기본 `7d` | | `CORS_ORIGINS` | - | 허용 도메인 (쉼표 구분) | | `PORT` | - | 기본 `3001` | **Frontend** (`frontend/.env.local`) | 변수 | 설명 | |------|------| | `NEXT_PUBLIC_API_URL` | 기본 `http://localhost:3001/api` | ## 배포 ```bash cd /path/to/reloop-v2 # 풀 배포 (백엔드 + 프론트엔드) cd backend && npx prisma generate && npx prisma migrate deploy && rm -f *.tsbuildinfo && pnpm build && pm2 restart reloop-api cd ../frontend && pnpm build && cp -r .next/static .next/standalone/.next/ && cp -r public .next/standalone/ && pm2 restart reloop-web ``` ## 주요 API 엔드포인트 | Method | Endpoint | 설명 | |--------|----------|------| | POST | `/api/auth/register` | 회원가입 | | POST | `/api/auth/login` | 로그인 | | GET | `/api/auth/me` | 내 정보 | | PATCH | `/api/me/profile` | 프로필 수정 (페르소나 변경 시 스케줄 재계산) | | PATCH | `/api/me/subscription-tier` | 구독 티어 전환 (Free/Pro/School) | | GET | `/api/dashboard/summary` | 대시보드 요약 | | GET | `/api/reviews/queue` | 복습 큐 (Free 10개 제한, 밀린 복습 자동 이월) | | POST | `/api/reviews/:id/submit` | 복습 결과 제출 | | GET | `/api/reviews/calendar` | 월간 복습 캘린더 | | GET | `/api/reviews/day` | 일별 복습 상세 | | POST | `/api/study-logs` | 학습 기록 생성 | | POST | `/api/study-logs/from-problem-set` | 모의고사 일괄 제출 | | POST | `/api/study-logs/parse-pdf` | PDF 문제 분리 | | GET | `/api/problem-sets` | 문제집 목록 | | GET | `/api/subjects` | 과목 목록 (Free 3개 제한) | | GET | `/api/stats/mastery-path` | 마스터리 경로 (Pro 전용) | | POST | `/api/assignments` | 과제 생성 (일괄/개인/복습) | | GET | `/api/assignments/:id/submissions/:userId/details` | 학생 풀이 상세 | ## 라이선스 UNLICENSED (비공개)