나리
전시만드는 방식문의
←블로그 목록
기능 소개2026-06-30LevelUp Piano — MIDI 피아노 연습 앱

80점 말고, 몇 마디를 다시 — 학습 진단과 간격 반복

마디·손 단위로 약점을 짚어 '3~7마디만 왼손으로 다시' 같은 타겟 재연습을 제안하고, 시간이 지나 다시 물어보는 간격 반복으로 약점을 굳히는 적응형 학습 설계입니다.

학습 설계데이터적응형UX
마디×손진단 단위
타겟재연습 (범위·손·템포)
간격반복약점 복습
최근 N세션만 보존

"80점"은 다음 행동을 알려주지 않는다

연습을 끝내고 "80점"이 뜨면, 기분은 알 수 있지만 무엇을 다시 해야 할지는 모릅니다. 점수는 결과이지 처방이 아닙니다. 좋은 연습 도구라면 "그래서 지금 뭘 하면 되는데?"에 답해야 합니다.

그래서 LevelUp Piano는 채점을 곡 단위가 아니라 마디·손 단위로 잘게 기록합니다.

마디와 손으로 쪼갠 데이터

12345678RL→ 타겟 재연습: 3~7마디 · 왼손(L)
마디(가로) × 손(R/L) 정확도 히트맵 — 초록은 높음, 붉을수록 낮음. 약한 구간이 곧 재연습 처방이 된다.

한 세션의 판정 결과를, 각 음이 속한 마디와 손(왼손·오른손)으로 집계합니다. 그러면 "이 곡 80점"이 아니라 "5마디 왼손 정확도가 특히 낮음" 같은 구체적 지도가 나옵니다.

약점은 어떻게 계산하나

각 (마디, 손) 버킷마다 Perfect·Good·Bad·Miss 개수를 세고, 정확도를 이렇게 매깁니다 — 애매하게 맞은 Good은 절반만 인정합니다.

// (마디, 손) 버킷의 정확도 — Good은 0.5로 가중
fun measureAccuracy(s: MeasureStat): Double =
    if (s.total <= 0) 0.0 else (s.perfect + s.good * 0.5) / s.total

이 정확도가 낮은 버킷이 곧 약점입니다. 연속된 약한 마디를 하나로 묶어 "3~7마디 왼손" 같은 타겟 재연습 후보로 제안합니다.

약점 → 타겟 재연습

마디 골라 연습 다이얼로그
마디 골라 연습 — 마디 범위 · 손(오른손/왼손/양손) · 느리게(템포) · 반복을 골라 약한 구간만

이 지도에서 곧바로 행동을 제안합니다. 사용자는 곡 전체를 처음부터 반복하는 대신, 필요한 부분만 다시 칠 수 있습니다.

  • 마디 범위 선택 — 예: 3~7마디만
  • 손 선택 — 왼손만 / 오른손만 / 양손
  • 템포 조절 — 느리게 시작해 올리기
  • 루프 — 그 구간을 반복

"곡 전체를 열 번"보다 "약한 5마디를 왼손으로 느리게 열 번"이 훨씬 효율적입니다. 진단이 곧 재연습 설정으로 이어지도록 설계해, 발견과 실행 사이의 마찰을 없앴습니다.

간격 반복 — 잊을 때쯤 다시

한 번 잘 쳤다고 끝이 아닙니다. 사람은 잊습니다. 그래서 간격 반복을 붙였습니다. 어학 앱의 복습 카드와 같은 원리(SM-2 계열)를 피아노 마디에 적용한 것입니다.

마디마다 복습 스케줄을 두고, 정확도가 통과선(80%) 이상이면 다음 간격으로 넘어가고, 미달이면 처음으로 되돌립니다. 간격은 1일 → 3일 → 7일 → 14일로 늘어납니다.

private val reviewIntervals = listOf(1, 3, 7, 14) // days
// 통과(정확도 ≥ 0.8)하면 reps 전진, 실패하면 0으로 리셋 → 1일부터 다시
val nextReps = if (accuracy >= 0.8) reps + 1 else 0
val dueAt = now.plusDays(reviewIntervals[nextReps.coerceIn(0, 3)])

기한이 된 마디는 한 번에 최대 5개까지 꺼내 "오늘 복습할 마디"로 제안합니다.

서사가 되는 진도: 마스터리와 주간 리캡

낱낱의 데이터는 서사로 묶여야 동기가 됩니다.

  • 마스터리 뷰 — 곡·구간별로 얼마나 익었는지를 한눈에.
  • 주간 리캡 — 이번 주 무엇을 얼마나 연습했는지 요약해, "내가 나아가고 있다"는 감각을 줍니다.

데이터는 가볍게

마디 단위 통계는 세션마다 쌓이면 금세 방대해집니다. 그래서 (마디, 손) 통계는 곡·학생별로 최근 10세션만 보존하고 그보다 오래된 세션은 지웁니다. 진단에는 오래된 전체 이력보다 최근 상태가 중요하니까요. 적응형 학습은 "모든 걸 영원히 저장"이 아니라 "지금 결정에 필요한 만큼"이면 충분합니다.

📝 아직 측정 전 — 검증할 가설

출시 초기라 "타겟 재연습이 실제로 정확도를 얼마나 올렸는가"는 아직 측정하지 못했습니다. 검증할 지표는 명확합니다 — 같은 (마디, 손)의 재연습 전후 정확도 상승, 복습 재방문율, 전체곡 재시도 통과율.

💡 Insight

점수는 결과이지 처방이 아니다. 마디·손 해상도로 잡은 데이터라야 "여기를, 이렇게 다시"라는 실행 가능한 처방으로 바뀐다.

마치며

적응형 학습의 핵심은 화려한 AI가 아니라 올바른 입도(granularity) 였습니다. 곡이 아니라 마디, 통짜가 아니라 손 — 이 해상도로 데이터를 잡으니, 진단이 곧 실행 가능한 처방이 되고, 간격 반복이 그 처방을 습관으로 굳힙니다. "다시 하라"가 아니라 "여기를, 이렇게 다시 하라"고 말해주는 것이 목표였습니다.

measure×handdiagnosis unit
targetedre-practice (range·hand·tempo)
spacedweak-spot review
recent Nsessions kept

"80 points" doesn't tell you your next move

Finish practicing and see "80 points," and you know how you feel — but not what to redo. A score is an outcome, not a prescription. A good practice tool has to answer "so what do I do now?"

So LevelUp Piano records grading not per song but finely, at the measure and hand level.

Data split by measure and hand

12345678RL→ targeted re-practice: measures 3–7 · left hand (L)
Accuracy heatmap of measures (columns) × hands (R/L) — green is high, redder is lower. The weak region becomes the re-practice prescription.

A session's judgment results are aggregated by the measure each note belongs to and by hand (left/right). Instead of "80 on this song," you get a concrete map: "measure 5, left hand accuracy is especially low."

How is weakness computed?

For each (measure, hand) bucket, count the Perfect/Good/Bad/Miss hits and score accuracy like this — a marginal Good only counts half.

// Accuracy of a (measure, hand) bucket — Good is weighted 0.5
fun measureAccuracy(s: MeasureStat): Double =
    if (s.total <= 0) 0.0 else (s.perfect + s.good * 0.5) / s.total

Low-accuracy buckets are the weak spots. Consecutive weak measures are merged into a single targeted-practice candidate like "measures 3–7, left hand."

Weakness → targeted re-practice

Choose-measures practice dialog
Choose measures to practice — pick a measure range, hand (right/left/both), tempo, and loop to drill only the weak spots

From that map, the app suggests action immediately. Instead of repeating the whole song from the top, the user can redo only what's needed.

  • Measure range — e.g., just measures 3–7
  • Hand — left only / right only / both
  • Tempo — start slow, ramp up
  • Loop — repeat that section

"The weak 5 measures, left hand, slow, ten times" beats "the whole song, ten times." By wiring diagnosis directly into re-practice settings, we removed the friction between discovering a problem and acting on it.

Spaced repetition — again, just as you'd forget

Playing it well once isn't the end. People forget. So there's spaced repetition — the review-card principle of language apps (SM-2 style), applied to piano measures.

Each measure carries a review schedule: if accuracy clears the pass line (80%) it advances to the next interval; if not, it resets to the start. The intervals grow 1 → 3 → 7 → 14 days.

private val reviewIntervals = listOf(1, 3, 7, 14) // days
// pass (accuracy ≥ 0.8) advances reps; a fail resets to 0 → back to 1 day
val nextReps = if (accuracy >= 0.8) reps + 1 else 0
val dueAt = now.plusDays(reviewIntervals[nextReps.coerceIn(0, 3)])

Measures that come due are pulled up to five at a time as "measures to review today."

Progress as a story: mastery and weekly recap

Individual data points only motivate once bound into a narrative.

  • Mastery view — how well you've learned each song and section, at a glance.
  • Weekly recap — a summary of what and how much you practiced this week, giving the feeling of "I'm moving forward."

Keep the data light

Measure-level stats pile up fast across sessions. So per song and student, (measure, hand) stats keep only the most recent 10 sessions and older ones are pruned — for diagnosis, recent state matters more than the full history. Adaptive learning isn't "store everything forever" — "as much as this decision needs" is enough.

📝 Not yet measured — hypotheses to verify

It's early post-launch, so "how much did targeted re-practice actually raise accuracy?" isn't measured yet. The metrics to verify are clear — before/after accuracy gains on the same (measure, hand), review return rate, and full-song retry pass rate.

💡 Insight

A score is an outcome, not a prescription. Only data captured at measure-and-hand resolution turns into an actionable "redo this, this way."

Closing

The heart of adaptive learning wasn't fancy AI but the right granularity. Measures, not songs; per-hand, not lumped together — capturing data at that resolution turns diagnosis into an actionable prescription, and spaced repetition hardens that prescription into a habit. The goal was to say not "do it again," but "redo this, this way."

관람해 주셔서 고맙습니다

© 2026 나리인포메이션(Nari Information). All rights reserved.

사업자등록번호 746-08-03415 · hello@nariinfo.dev

LevelUp PianoMazzucchiVault