README.md 전면 재작성 + docs/ 5개 문서: - algorithm.md: 망각 곡선 수식, 페르소나, S₀ 업데이트, FSRS 비교 - architecture.md: 시스템 구조, 모듈 설명, 라우트 맵, ER 다이어그램 - user-guide.md: 기능별 사용법, 페르소나 가이드, FAQ - admin-guide.md: 배포, KICE 데이터 관리, PM2, 보안 체크리스트 - pdf-pipeline.md: 파싱 흐름, 이미지 크롭 알고리즘, OCR, 전략 패턴
5.4 KiB
5.4 KiB
ReLoop 알고리즘 상세
개요
ReLoop은 에빙하우스 망각 곡선(Ebbinghaus forgetting curve)에 "페르소나"라는 개인화 레이어를 얹은 자체 복습 스케줄링 알고리즘을 사용합니다. FSRS(Free Spaced Repetition Scheduler)나 Anki의 SM-2와는 다른 독자적 모델입니다.
핵심 아이디어: 사람마다 잊는 속도가 다르고, 같은 사람도 쉬운 문제와 어려운 문제를 다른 속도로 잊는다. ReLoop은 이 두 축(페르소나 × 난이도)을 수학적으로 모델링합니다.
수학적 모델
1. 실력 감쇄 함수 (Skill Decay)
S(t) = S₀ × exp(-λ × Δt)
- S₀: 마지막 학습/복습 직후의 실력 수준 (0~1 사이 실수)
- λ (lambda): 페르소나별 망각 속도 계수 (단위: 1/일)
- Δt: 마지막 학습으로부터 경과한 일수
- S(t): 현재 시점의 실력 수준
시간이 지날수록 S(t)는 지수적으로 감소합니다. λ가 클수록 빠르게 잊습니다.
2. 정답 확률 함수 (Recall Probability)
P(correct) = σ(k × (S(t) - D))
여기서 σ는 시그모이드 함수:
σ(x) = 1 / (1 + exp(-x))
- k: 시그모이드 기울기 상수 (기본값 4.0). 클수록 실력과 난이도의 차이에 민감하게 반응
- D: 문제 난이도 (0~1). 기출 문제의 경우
1 - 공개된정답률로 계산 - P: 이 문제를 지금 풀면 맞힐 확률 (0~1)
직관적으로: 실력 S(t)가 난이도 D보다 높으면 맞힐 확률이 높고, 낮으면 떨어집니다.
3. 복습 시점 결정 (Scheduling)
사용자의 복습 민감도(intensity)에 따라 P_threshold가 정해지고, P가 이 기준 아래로 떨어지는 시점을 다음 복습일로 잡습니다.
방정식을 Δt에 대해 풀면:
Δt = -(1/λ) × ln((D + logit(P_threshold)/k) / S₀)
여기서 logit(p) = ln(p / (1-p))입니다.
4. 경계 조건
| 상황 | 처리 |
|---|---|
| 계산된 Δt < 0 (이미 기준 이하) | 1시간 후 복습 |
| target 값 ≤ 0 (매우 쉬운 문제) | 60일 후 (최대 간격) |
| target > S₀ (실력이 기준에 한참 못 미침) | 1시간 후 복습 |
| Δt > 60일 | 60일로 캡 |
페르소나 시스템
사용자는 4가지 페르소나 중 하나를 선택합니다. 각 페르소나는 서로 다른 망각 속도(λ)를 가집니다.
페르소나별 λ 값
| 페르소나 | λ | 의미 | 적합한 학습자 |
|---|---|---|---|
| Senior (숙련자) | 0.1 | 천천히 잊음 | 기초가 탄탄한 학습자. 한 번 배우면 오래 기억 |
| Mid (중급) | 0.2 | 보통 속도 | 대부분의 학습자에게 추천 (기본값) |
| Junior (초보) | 0.4 | 빠르게 잊음 | 새로운 분야를 시작한 학습자 |
| Crammer (단기집중) | 0.6 | 매우 빠르게 잊음 | 시험 직전 단기 반복 학습 |
실제 복습 주기 예시 (난이도 0.5, moderate 민감도)
| 페르소나 | 정답 후 S₀ | 다음 복습까지 |
|---|---|---|
| Senior | 0.75 | ~4일 |
| Mid | 0.75 | ~2일 |
| Junior | 0.75 | ~1일 |
| Crammer | 0.75 | ~12시간 |
복습 민감도 (Review Intensity)
| 설정 | P_threshold | 의미 |
|---|---|---|
| 엄격 (strict) | 0.70 | 정답 확률이 70% 아래로 떨어지면 바로 복습. 가장 자주 복습 |
| 균형 (moderate) | 0.50 | 50% 기준. 추천 기본값 |
| 여유 (relaxed) | 0.35 | 35%까지 허용. 최소한의 복습으로 유지 |
S₀ 업데이트 규칙
학습/복습 결과에 따라 실력 값 S₀가 업데이트됩니다:
| 결과 | 수식 | 예시 (이전 S₀=0.5) |
|---|---|---|
| 정답 | new_S₀ = old_S₀ × 0.5 + 0.6 |
0.85 |
| 부분 정답 | new_S₀ = old_S₀ × 0.7 + 0.3 |
0.65 |
| 오답 | new_S₀ = old_S₀ × 0.5 |
0.25 |
- 정답을 맞히면 S₀가 크게 올라가고, 오답이면 절반으로 떨어집니다.
- S₀는 항상 0~1 범위로 클램핑됩니다.
- 첫 학습 시 S₀ 초기값은 문제의
baseCorrectRate(공개 정답률)이 있으면 그 값을 기반으로, 없으면 0.3을 사용합니다.
Anki / FSRS와의 차이
| ReLoop | Anki (SM-2) | FSRS | |
|---|---|---|---|
| 개인화 축 | 페르소나 (4종) | Easy/Good/Hard 버튼 | 학습자별 최적화 파라미터 |
| 난이도 모델 | 문제별 고정 (baseCorrectRate) | 카드별 Ease factor | 카드별 Difficulty |
| 간격 계산 | 연속 함수 (지수 감쇄) | 정수 배수 (×2.5 등) | 연속 함수 (power law) |
| 결과 입력 | 3단계 (정답/부분/오답) | 4단계 (Again/Hard/Good/Easy) | 4단계 |
| 복잡도 | 낮음 (파라미터 6개) | 중간 | 높음 (파라미터 19개) |
구현 위치
backend/src/forget/persona-forget.service.ts— 알고리즘 핵심 클래스backend/src/reviews/reviews.service.ts— 복습 큐 관리 + 스케줄 생성backend/src/study-logs/study-logs.service.ts— 학습 기록 생성 시 S₀ 업데이트 + ReviewSchedule 생성
향후 개선 방향
- per-user λ 학습: 사용자의 실제 복습 결과를 축적해 λ를 자동 조정 (현재는 페르소나로 고정)
- FSRS 하이브리드: power-law 기반 감쇄를 옵션으로 추가
- 태그별 λ: 같은 사용자라도 과목/태그에 따라 다른 망각 속도 적용
- 최적 복습량 상한: 하루 복습 큐가 너무 길어지지 않도록 우선순위 기반 필터링