팀스파르타는 코딩 부트캠프의 수강 운영 데이터를 가진 곳이라, 수강생 이탈·막힘을 짚어 튜터 우선순위를 매기는 이 도구는 팀스파르타의 실제 수강 데이터가 있어야 우선순위를 검증한다.
'튜터 대규모 모집, 프로덕트엔지니어링'. 튜터 개입 우선순위가 학습 운영의 핵심.
'PO(프로덕트오너), PM'. 이탈·막힘 점검이 학습 성과 운영의 토대.
'백엔드/서버개발'. 학습 데이터 파이프라인+점검이 1주 단위.
수강생 학습·과제 데이터를 받아 이탈 위험과 막힌 지점을 규칙으로 짚고, 튜터 개입 우선순위를 근거와 함께 매기는 1주 포트폴리오.
팀스파르타 PE. 수강생 이탈을 튜터가 일일이 보던 일을, 자동 점검 + 개입 우선순위 도구로 옮기고 싶은 사람.
학습에 진도·과제를 붙이면, 도구가 (a) 이탈·막힘을 규칙으로 짚고 (b) 튜터 개입 우선순위를 근거와 함께 매길 수 있다.
학습·과제 데이터를 받아 이탈·막힘을 짚고 튜터 개입 우선순위를 근거와 함께 내는 동작하는 도구.
이탈 위험 신호를 다음 주 실제 이탈과 맞춰 적중률을 재고, 오탐을 보여주는 대시보드.
우선순위 높은 수강생을 튜터에게 자동 알림하고 추적하는 단계.
학습 데이터를 넣으면 이탈·막힘과 튜터 우선순위가 근거와 함께 나오는 걸 시연한다
이탈·막힘 규칙 판정이 정답과 일치하는 비율 100%
측정: 결정적 재계산, 표본: 수강생 200건
일부러 만든 결측·경계·미등록 수강생 30종을 넣어도 점검이 멈추지 않고 처리되는 걸 시연한다
위 수치는 더미데이터 자가채점이며, 실제 이탈 예측 정확도는 팀스파르타 실데이터 + 실 검수자가 있어야 측정 가능. 이 포트폴리오는 그 검증을 바로 돌릴 수 있는 상태까지 만든다.
이건 고객·실데이터 없이 혼자 만든 포트폴리오라 모든 수치는 합성 데이터 자가채점이다. 면접에서 '데모 동작 + 실검증 준비 상태'로 솔직히 설명하는 게 오히려 신뢰를 준다
정답을 내가 만들었으니 잘 맞는 게 당연. 그래서 결측·경계·미등록·표기 흔들림 케이스를 더미에 일부러 섞어 쉬운 문제만 푸는 게 아님을 보여준다
상관≠인과: 활동 저하가 곧 이탈은 아니므로 '위험 신호'로만 표시한다
실제 도입 시 달라지는 것: 실 학습 패턴·코스가 더미와 다르므로 이탈 규칙을 실데이터로 맞춰야 한다(도입 단계 과제)
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
수강생 학습·과제를 묶어 이탈·막힘 점검 입력으로 쓴다
| student_id | name_raw | student_key | course | progress | last_active | assignments_done |
|---|---|---|---|---|---|---|
| ST900 | 홍OO(영문) | — | 웹개발 | — | — | — |
| ST901 | 수강생0 | st0 | 데이터 | 0 | 2026-04-01 | 0 |
| ST902 | 완주생 | st2 | 앱 | 1 | 2026-05-23 | 10 |
| ST903 | 미등록수강생 | — | 웹개발 | 0.5 | 2026-05-10 | — |
| ST000 | 수강생0 | st0 | 웹개발 | 0.1 | 2026-05-22 | 0 |
z.object({ student_id: z.string(), name_raw: z.string(), student_key: z.string().nullable(), course: z.string(), progress: z.number().nullable(), last_active: z.string().nullable(), assignments_done: z.number().nullable() }). 쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞어라: progress/last_active/assignments null(미활동), progress 0/1 극단, 오래된 last_active(이탈), student_key null 미등록, name_raw 국문/영문 병기. 형식 깨뜨리기 시도 3건도 별도로.z.object({ student_id: z.string(), name_raw: z.string(), student_key: z.string().nullable(), course: z.string(), progress: z.number().nullable(), last_active: z.string().nullable(), assignments_done: z.number().nullable() })| Python | 학습 데이터 ingest + 이탈 규칙 + eval(공고 스택 미명시 → 도메인 기반 추론) |
| TypeScript | 대시보드 렌더 + Zod 검증 |
| React | 학습 운영 대시보드 |
| Node.js | 점검 API |
| PostgreSQL | 학습 단일 진실원 |
| LLM | 막힌 지점 분석 + 우선순위 설명 |
✓ pass → 그대로 멈춰도 완성품. 더 키우려면 2주차(예측 검증)로.
✓ pass → 여기서 멈춰도 완결. 더 키우려면 3주차(자동 개입 알림)로.
이탈·막힘 + 튜터 우선순위
z.object({ student_id: z.string(), risk: z.enum(['low','high','review']), stuck_at: z.string().nullable(), priority: z.number(), evidence: z.array(z.object({ field: z.string(), value: z.number() })) })[
{
"student_id": "ST901",
"risk": "high",
"stuck_at": "2주차 과제",
"priority": 1,
"evidence": [
{
"field": "progress",
"value": 0
}
]
},
{
"student_id": "ST900",
"risk": "review",
"stuck_at": null,
"priority": 3,
"evidence": []
}
]risk 규칙·evidence 정합성은 자동 검증, priority/stuck_at 타당성은 튜터/judge 검증.