학생 진도 추적 시스템

선생님은 각 학생의 학습 진행 상황을 개별적으로 상세히 확인할 수 있습니다.

개요

주요 기능

1. 학생 목록 페이지

전체 학생 목록을 한눈에 확인:

2. 개별 학생 진도 페이지

학생 정보 헤더

통계 카드 (8개)

탭 인터페이스

과제 탭

퀴즈 탭

일기 탭

출석 탭

API 엔드포인트

GET /api/teacher/students?community=slug

모든 학생 목록 조회

Response:

{ "students": [ { "id": 1, "userId": 10, "name": "김철수", "avatar": "/avatars/user1.jpg", "level": 5, "points": 1250, "streak": 15, "role": "student", "joinedAt": "2025-01-01T00:00:00.000Z" } ] }

GET /api/teacher/students/[memberId]/progress?community=slug

개별 학생 상세 진도 조회

Response:

{ "student": { "id": 1, "userId": 10, "name": "김철수", "avatar": "/avatars/user1.jpg", "level": 5, "points": 1250, "streak": 15, "role": "student", "joinedAt": "2025-01-01T00:00:00.000Z" }, "stats": { "totalAssignments": 10, "completedAssignments": 8, "assignmentCompletionRate": 80, "avgAssignmentScore": 85, "totalQuizzes": 5, "completedQuizzes": 4, "quizCompletionRate": 80, "avgQuizScore": 82, "totalDiaries": 15, "totalAttendance": 20 }, "assignments": [ { "id": "123", "assignmentId": "45", "title": "한국어 작문 과제 1", "score": 85, "maxScore": 100, "status": "graded", "submittedAt": "2025-12-10T10:30:00.000Z", "gradedAt": "2025-12-11T15:00:00.000Z" } ], "quizzes": [ { "id": "456", "quizId": "78", "title": "TOPIK 모의고사 1", "score": 82, "maxScore": 100, "completedAt": "2025-12-09T14:00:00.000Z" } ], "diaries": [ { "id": "789", "title": "오늘은 한국어 수업이 재미있었다...", "status": "reviewed", "createdAt": "2025-12-08T20:00:00.000Z" } ], "attendance": [ { "id": "321", "sessionCode": "ABC12345", "markedAt": "2025-12-14T13:02:00.000Z" } ] }

데이터 계산 로직

완료율 계산

const assignmentCompletionRate = totalAssignments > 0 ? Math.round((completedAssignments / totalAssignments) * 100) : 0; const quizCompletionRate = totalQuizzes > 0 ? Math.round((completedQuizzes / totalQuizzes) * 100) : 0;

평균 점수 계산

const avgAssignmentScore = submissions.length > 0 ? Math.round( submissions.reduce((sum, s) => { const score = s.submission.manualScore ?? s.submission.score ?? 0; return sum + score; }, 0) / submissions.length ) : 0; const avgQuizScore = quizResults.length > 0 ? Math.round( quizResults.reduce((sum, q) => sum + (q.attempt.score || 0), 0) / quizResults.length ) : 0;

점수 우선순위

과제 점수는 수동 점수 우선, AI 점수 차선:

const score = submission.manualScore ?? submission.score ?? null;

UI 컴포넌트

학생 카드 (목록 페이지)

<Card> <Avatar src={student.avatar} /> <Name>{student.name}</Name> <Badge>레벨 {student.level}</Badge> <Points>{student.points}점</Points> <Streak>🔥 {student.streak}일</Streak> <RoleBadge>{student.role}</RoleBadge> </Card>

통계 카드 (상세 페이지)

<StatCard> <Icon /> {/* 과제, 퀴즈 등 */} <Label>과제 완료율</Label> <Value>{stats.assignmentCompletionRate}%</Value> </StatCard>

탭 인터페이스

<Tabs defaultValue="assignments"> <TabsList> <TabsTrigger value="assignments">과제</TabsTrigger> <TabsTrigger value="quizzes">퀴즈</TabsTrigger> <TabsTrigger value="diaries">일기</TabsTrigger> <TabsTrigger value="attendance">출석</TabsTrigger> </TabsList> <TabsContent value="assignments">...</TabsContent> </Tabs>

검색 기능

실시간 검색

useEffect(() => { if (searchQuery.trim() === "") { setFilteredStudents(students); } else { const query = searchQuery.toLowerCase(); setFilteredStudents( students.filter((student) => student.name?.toLowerCase().includes(query)) ); } }, [searchQuery, students]);

사용 시나리오

일일 모니터링

  1. 학생 목록 페이지 접속
  2. Streak이 0인 학생 확인 (관심 필요)
  3. 해당 학생 클릭 → 상세 진도 확인
  4. 과제 완료율, 출석률 분석
  5. 필요 시 개별 상담 진행

학기말 평가

  1. 각 학생 상세 페이지 접속
  2. 과제 탭에서 전체 제출 현황 확인
  3. 퀴즈 탭에서 평균 점수 확인
  4. 통계 카드로 종합 성적 파악
  5. 성적표 작성 또는 피드백 제공

개별 상담 준비

  1. 상담 대상 학생 페이지 접속
  2. 일기 탭에서 최근 감정 상태 파악
  3. 출석 탭에서 참여도 확인
  4. 과제/퀴즈 탭에서 학습 수준 분석
  5. 맞춤형 학습 계획 수립

권한 관리

Owner & Admin

Student

성능 최적화

데이터 로딩

쿼리 최적화

// 필요한 컬럼만 선택 .select({ memberId: communityMembers.id, userId: users.id, name: users.name, nameKr: users.nameKr, avatar: users.avatar, })

캐싱

확장 가능성

향후 추가 기능

트러블슈팅

학생 목록이 비어있는 경우

통계가 0으로 표시되는 경우

평균 점수가 이상한 경우

일기/출석이 표시되지 않는 경우