README.md 전면 재작성 + docs/ 5개 문서: - algorithm.md: 망각 곡선 수식, 페르소나, S₀ 업데이트, FSRS 비교 - architecture.md: 시스템 구조, 모듈 설명, 라우트 맵, ER 다이어그램 - user-guide.md: 기능별 사용법, 페르소나 가이드, FAQ - admin-guide.md: 배포, KICE 데이터 관리, PM2, 보안 체크리스트 - pdf-pipeline.md: 파싱 흐름, 이미지 크롭 알고리즘, OCR, 전략 패턴
6.2 KiB
6.2 KiB
ReLoop 시스템 아키텍처
전체 구성
┌──────────────┐
│ Nginx │
│ (리버스 프록시) │
└──┬───────┬───┘
│ │
reloop.nabomhalang.co.kr reloop-api.nabomhalang.co.kr
│ │
┌────────┘ └────────┐
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Next.js 14 │ │ NestJS 10 │
│ (프론트엔드) │ │ (API 서버) │
│ Port 3000 │ │ Port 3001 │
│ PM2: reloop-web │ │ PM2: reloop-api │
└──────────────────┘ └────────┬─────────┘
│
┌────────┴────────┐
│ MariaDB │
│ Port 33006 │
│ DB: reloop_v2 │
└─────────────────┘
백엔드 모듈 구조
인증 (auth/)
- JWT 기반 stateless 인증
POST /auth/register— 회원가입 (bcrypt 해시)POST /auth/login— 로그인 (JWT 발급, 7일 만료)GET /auth/me— 현재 사용자 정보 (JwtAuthGuard)- 모든 보호 라우트는
@UseGuards(JwtAuthGuard)로 보호
프로필 (me/)
PATCH /me/profile— 닉네임, 페르소나, 등급, 리뷰 민감도, 목표 연도, 중점 과목 등 수정POST /me/avatar— 아바타 이미지 업로드 (multipart/form-data, 최대 2MB, jpeg/png/webp)- 업로드 파일은
backend/uploads/avatars/에 저장,/uploads/avatars/URL로 서빙
문제집 (problem-sets/)
GET /problem-sets— 문제집 목록 (년도, 과목 필터 가능)GET /problem-sets/:id— 문제집 상세 (문항 + 지문 포함)- 문제집은 공유 자원 (모든 사용자가 동일한 문제집 접근)
학습 기록 (study-logs/)
POST /study-logs— 개별 학습 기록 생성POST /study-logs/from-problem-set— 모의고사 일괄 제출 (자동 채점 + Subject/Tag 자동 생성 + ReviewSchedule 생성)GET /study-logs— 내 학습 기록 목록GET /study-logs/:id— 상세 (문제 정보 + 리뷰 스케줄 포함)PATCH /study-logs/:id— 수정 (chosenAnswer, result, memo)
복습 (reviews/)
GET /reviews/queue— 오늘의 복습 큐 (scheduledAt이 현재 이전인 ReviewSchedule 조회)POST /reviews/:id/submit— 복습 결과 제출 → S₀ 업데이트 → 다음 ReviewSchedule 생성- 복습 큐는
PersonaForgetService.schedule()이 결정한 날짜에 따라 자동으로 채워짐
망각 곡선 엔진 (forget/)
PersonaForgetService— 순수 계산 서비스 (DB 접근 없음)updateS0(input)— 결과에 따른 실력 업데이트schedule(input)— 다음 복습 시점 계산predictP(opts)— 특정 시점의 정답 확률 예측 (통계용)sampleCurve(opts)— 시간에 따른 실력/확률 곡선 샘플링 (차트용)
통계 (stats/)
GET /stats/subjects— 과목별 통계 (S₀ 평균, 태그 수)GET /stats/mastery-path— 숙련도 성장 곡선 데이터 (태그별 시계열)
보안
helmet— HTTP 보안 헤더@nestjs/throttler— 전역 60req/min, 인증 엔드포인트 10req/min- CORS whitelist (
CORS_ORIGINS환경변수) ValidationPipe— 요청 body 화이트리스트 + 자동 변환
프론트엔드 라우트 맵
| 경로 | 인증 | 설명 |
|---|---|---|
/ |
공개 | 랜딩 페이지 (로그인 시 대시보드 리다이렉트) |
/login |
공개 | 로그인 |
/register |
공개 | 회원가입 |
/pricing |
공개/로그인 | 플랜 (비로그인: 마케팅, 로그인: 현재 플랜 표시) |
/privacy /terms /contact |
공개 | 법적 페이지 |
/onboarding |
로그인 | 신규 사용자 온보딩 (등급, 과목, 페르소나) |
/dashboard |
로그인 | 대시보드 (채움/빈 상태 자동 분기) |
/exams |
로그인 | 문제집 카탈로그 |
/study/exam/[id] |
로그인 | 모의고사 시험 화면 |
/study/exam/[id]/result |
로그인 | 시험 결과 |
/study |
로그인 | 학습 기록 직접 입력 |
/study/history |
로그인 | 학습 기록 히스토리 |
/study-logs/[id] |
로그인 | 학습 기록 상세 |
/solve/[id] |
로그인 | 개별 문제 풀기 |
/review |
로그인 | 복습 세션 |
/stats |
로그인 | 통계 (히트맵, 정답률, 성장 곡선) |
/subjects |
로그인 | 과목 및 태그 관리 |
/profile |
로그인 | 프로필 + 학습 설정 + 알림 + 계정 |
DB 스키마 (ER)
User ─────┬──> Subject ──> Tag
│ │ │
│ ▼ ▼
├──> StudyLog ◄────┘
│ │
│ ▼
└──> ReviewSchedule
│
└──> SkillSnapshot (태그별 S₀)
ProblemSet ──> Problem
│ │
└──> Passage ◄── Problem.passageId
주요 모델
- User: 이메일, 비밀번호(bcrypt), 닉네임, 페르소나, 등급, 복습 민감도, 구독 티어
- Subject: 사용자별 과목 (이름, 색상). 과목 안에 Tag 목록
- Tag: 과목 하위 태그 (예: 수학 > 미적분). SkillSnapshot과 1:1
- StudyLog: 학습 기록 한 건 (결과, 난이도, 메모, 시간, 선택한 답)
- ReviewSchedule: 복습 스케줄 (예정일, 상태, 반복 회차, 예측 정답률)
- SkillSnapshot: 태그별 최신 S₀ (실력 수치)
- ProblemSet: 문제집 (제목, 시험 유형, 연도, 과목명, 오디오 경로)
- Problem: 개별 문항 (번호, 본문, 선택지, 정답, 이미지 URL, 난이도)
- Passage: 공통 지문 (본문, 범위, 이미지 URL)