57cd3051666aa52bbd67b55687ec77f16ea3ef5e
기존 exclude 패턴 'prisma' 는 backend/prisma/ 스키마 폴더를 제외하려는 의도였지만, TypeScript exclude glob 이 경로 어디서든 'prisma' 디렉터리를 매칭해서 src/prisma/ 도 함께 제외됨. 그 결과 nest build 가 PrismaModule 을 dist/prisma.module.js 로 평탄화 emit 하면서 app.module 의 './prisma/prisma.module' require 가 런타임에 깨졌음. 이전 배포는 tsbuildinfo 캐시가 살아있던 덕에 우연히 정상 트리로 emit 되어 가려져 있었고, 오늘 클린 빌드 시 노출. 'prisma' 폴더의 .ts 파일들은 어차피 include 'src/**/*' 에 안 잡히므로 exclude 자체가 불필요. 항목 제거로 해결.
ReLoop v2
잊기 전에 다시 만나는 학습법. 페르소나 기반 망각 곡선으로 개인화된 복습 간격을 자동으로 계산하는 적응형 학습 플랫폼.
수능, 자격증, 어학, 취미 학습 — 어떤 공부든 ReLoop이 기억을 관리합니다.
핵심 기능
| 기능 | 설명 |
|---|---|
| 적응형 복습 스케줄링 | 페르소나 + 문제 난이도에 따라 "정답률이 기준 아래로 떨어지는 시점"을 자동 계산해 복습 큐에 넣습니다 |
| KICE 기출 문제집 | 2025/2026 수능 수학 4단원(공통/확률과 통계/미적분/기하) 92문항을 PDF에서 자동 크롭한 이미지로 제공 |
| 모의고사 모드 | 실제 시험처럼 타이머 + OMR 답안 선택 + 자동 채점 + 학습 기록 일괄 생성 |
| Solved.ac PS 연동 | Solved.ac 계정에서 최신 백준 풀이 이력을 동기화해 복습 큐에 추가 |
| 통계 대시보드 | 학습 히트맵, 단원별·PS 정답률, 숙련도 성장 곡선을 시각화 |
| PWA 지원 | 모바일 홈 화면에 앱으로 설치 가능 |
기술 스택
| 영역 | 기술 |
|---|---|
| Backend | NestJS 10 + Prisma 5 + MariaDB |
| Frontend | Next.js 14 (App Router) + React 18 + styled-components 6 |
| 인증 | JWT (passport-jwt) |
| 보안 | helmet, @nestjs/throttler (60req/min), CORS whitelist |
| 아이콘 | Phosphor React |
| 폰트 | Pretendard + Inter + JetBrains Mono |
| 배포 | PM2 on Debian VM, nginx reverse proxy |
| PDF 처리 | poppler-utils (pdftotext, pdftoppm, pdfinfo) |
| OCR | Codex CLI Vision (codex exec -i) |
프로젝트 구조
reloop-v2/
├── backend/ # NestJS API 서버
│ ├── src/
│ │ ├── auth/ # JWT 인증 (login, register, me)
│ │ ├── dashboard/ # 대시보드 요약 API
│ │ ├── forget/ # 페르소나 망각 곡선 엔진
│ │ ├── me/ # 프로필, 아바타 업로드
│ │ ├── problem-sets/ # 문제집 CRUD + 파싱 모듈
│ │ │ └── parsing/ # PDF 파싱 엔진 (범용, 전략 패턴)
│ │ │ ├── strategies/ # kice.ts, math.ts
│ │ │ └── ocr-fallback/ # Codex Vision OCR
│ │ ├── reviews/ # 복습 큐 관리
│ │ ├── stats/ # 통계 API
│ │ ├── study-logs/ # 학습 기록 + 모의고사 일괄 제출
│ │ ├── subjects/ # 과목 관리
│ │ └── tags/ # 태그 관리
│ ├── prisma/
│ │ ├── schema.prisma # DB 스키마
│ │ ├── seed.ts # 데모 데이터 시드
│ │ └── migrations/ # 마이그레이션 히스토리
│ ├── scripts/
│ │ ├── kice-import.ts # KICE PDF 임포트 CLI
│ │ └── ocr-fix.ts # OCR 보정 CLI
│ └── uploads/ # 문제 이미지, 아바타 (git 제외)
├── frontend/ # Next.js 프론트엔드
│ ├── src/
│ │ ├── app/ # App Router 페이지들
│ │ │ ├── dashboard/ # 대시보드 (채움/빈 상태)
│ │ │ ├── exams/ # 문제집 카탈로그
│ │ │ ├── study/
│ │ │ │ ├── exam/[id]/ # 모의고사 시험 화면
│ │ │ │ └── history/ # 학습 기록 히스토리
│ │ │ ├── review/ # 복습 세션
│ │ │ ├── solve/[id]/ # 개별 문제 풀기
│ │ │ ├── study-logs/[id]/ # 학습 기록 상세
│ │ │ ├── stats/ # 통계
│ │ │ ├── subjects/ # 과목 및 태그 관리
│ │ │ ├── profile/ # 프로필 + 설정 통합
│ │ │ ├── pricing/ # 플랜 (공개/로그인 분기)
│ │ │ ├── onboarding/ # 신규 사용자 온보딩
│ │ │ ├── login/ + register/ # 인증
│ │ │ ├── privacy/ terms/ contact/ # 법적 페이지
│ │ │ └── page.tsx # 랜딩 페이지
│ │ ├── components/
│ │ │ ├── ui/ # Button, Card, Icon, Toast, Select, DatePicker, ...
│ │ │ ├── layout/ # AppShell, SideNav, BottomNav
│ │ │ ├── auth/ # AuthCard (로그인/회원가입 통합)
│ │ │ ├── dashboard/ # EmptyDashboard
│ │ │ └── legal/ # LegalLayout
│ │ ├── lib/ # api.ts, auth.ts, constants.ts, exam-date.ts
│ │ └── styles/ # theme.ts (디자인 토큰, 애니메이션)
│ └── public/ # 정적 파일, PWA manifest, 아이콘
├── data/kice/ # KICE 원본 PDF (git 제외, 저작권)
│ ├── 2025/{국어,수학,영어,...}/
│ └── 2026/{국어,수학,영어,...}/
├── docs/ # 상세 매뉴얼
│ ├── algorithm.md # 망각 곡선 알고리즘 상세
│ ├── architecture.md # 시스템 아키텍처
│ ├── user-guide.md # 사용자 가이드
│ ├── admin-guide.md # 운영/배포 가이드
│ └── pdf-pipeline.md # PDF 파싱 파이프라인
└── Plans.md # 개발 계획 + 진행 상황
알고리즘 요약
상세 내용: docs/algorithm.md
ReLoop은 FSRS 대신 자체 페르소나 기반 망각 곡선을 사용합니다.
핵심 수식
실력 감쇄: S(t) = S₀ × exp(-λ × t)
정답 확률: P = sigmoid(k × (S(t) - D))
- S₀ (0~1): 마지막 학습 시점의 실력. 맞으면 올라가고 틀리면 떨어짐
- λ (lambda): 페르소나별 망각 속도. senior(0.1)은 느리게, crammer(0.6)은 빠르게 잊음
- D: 문제 난이도 (0~1)
- k: sigmoid 기울기 (기본 4.0)
복습 시점 결정
"정답 확률 P가 사용자의 기준(P_threshold) 아래로 떨어지는 시점"을 다음 복습일로 잡습니다.
| 복습 민감도 | P_threshold | 의미 |
|---|---|---|
| 엄격 (strict) | 0.7 | 70% 이하로 떨어지면 복습 |
| 균형 (moderate) | 0.5 | 50% 이하 |
| 여유 (relaxed) | 0.35 | 35% 이하 |
페르소나
| 페르소나 | λ (망각속도) | 복습 주기 경향 |
|---|---|---|
| Senior | 0.1 | 7~14일 (느린 망각) |
| Mid | 0.2 | 2~5일 |
| Junior | 0.4 | 1~2일 (빠른 망각) |
| Crammer | 0.6 | 매일~격일 |
S₀ 업데이트 규칙
| 결과 | 새 S₀ |
|---|---|
| 정답 | S₀ × 0.5 + 0.6 |
| 부분 | S₀ × 0.7 + 0.3 |
| 오답 | S₀ × 0.5 |
빠른 시작
필수 조건
- Node.js 20+
- pnpm 9+
- MariaDB/MySQL 8+
- poppler-utils (
pdftotext,pdftoppm,pdfinfo)
설치 및 실행
# 1. 클론
git clone ssh://git@your-gitea:2222/hanarang/reloop-v2.git
cd reloop-v2
# 2. 백엔드
cd backend
pnpm install
cp .env.example .env # DATABASE_URL, JWT_SECRET 편집
pnpm prisma migrate dev
pnpm prisma:seed # 데모 계정 생성
pnpm dev # http://localhost:3001
# 3. 프론트엔드 (새 터미널)
cd frontend
pnpm install
cp .env.example .env.local # NEXT_PUBLIC_API_URL 편집
pnpm dev # http://localhost:3000
# 4. (선택) KICE 기출 임포트
# data/kice/ 에 PDF 배치 후:
cd backend
pnpm cli:kice-import --year=2026
데모 계정
| 이메일 | 비밀번호 |
|---|---|
| demo@reloop.local | demo1234 |
환경 변수
Backend (backend/.env)
| 변수 | 필수 | 기본값 | 설명 |
|---|---|---|---|
DATABASE_URL |
O | — | mysql://user:pass@host:3306/reloop_v2 |
JWT_SECRET |
O | — | 32자 이상 랜덤 문자열 |
JWT_EXPIRES_IN |
— | 7d |
토큰 만료 기간 |
CORS_ORIGINS |
— | http://localhost:3000 |
쉼표 구분 허용 도메인 |
PORT |
— | 3001 |
API 서버 포트 |
Frontend (frontend/.env.local)
| 변수 | 필수 | 기본값 |
|---|---|---|
NEXT_PUBLIC_API_URL |
— | http://localhost:3001/api |
배포
상세 내용: docs/admin-guide.md
# 서버에서
cd /path/to/reloop-v2
# 백엔드
cd backend && pnpm install && pnpm prisma:deploy && pnpm build
pm2 restart reloop-api
# 프론트엔드
cd frontend && pnpm install && pnpm build
cp -r .next/static .next/standalone/.next/
cp -r public .next/standalone/
pm2 restart reloop-web
API 요약
상세 내용: docs/architecture.md
| Method | Endpoint | 설명 |
|---|---|---|
| POST | /api/auth/register |
회원가입 |
| POST | /api/auth/login |
로그인 (JWT 발급) |
| GET | /api/auth/me |
내 정보 |
| PATCH | /api/me/profile |
프로필 수정 |
| POST | /api/me/avatar |
아바타 업로드 |
| GET | /api/dashboard/summary |
대시보드 요약 |
| GET | /api/problem-sets |
문제집 목록 |
| GET | /api/problem-sets/:id |
문제집 상세 (문항 + 지문) |
| GET | /api/study-logs |
학습 기록 목록 |
| POST | /api/study-logs |
학습 기록 생성 |
| GET | /api/study-logs/:id |
학습 기록 상세 |
| PATCH | /api/study-logs/:id |
학습 기록 수정 |
| POST | /api/study-logs/from-problem-set |
모의고사 일괄 제출 |
| GET | /api/reviews/queue |
오늘의 복습 큐 |
| POST | /api/reviews/:id/submit |
복습 결과 제출 |
| GET | /api/subjects |
과목 목록 |
| GET | /api/stats/subjects |
과목별 통계 |
| GET | /api/stats/mastery-path |
숙련도 성장 곡선 |
라이선스
UNLICENSED (비공개)
Description
Languages
TypeScript
81.2%
HTML
18.7%