학생 진도 추적 시스템
선생님은 각 학생의 학습 진행 상황을 개별적으로 상세히 확인할 수 있습니다.
개요
- 학생 목록 경로:
/c/[slug]/students - 개별 학생 진도 경로:
/c/[slug]/students/[memberId] - 권한: Owner, Admin만 접근 가능
- 목적: 학생별 과제, 퀴즈, 일기, 출석 현황을 통합 관리
주요 기능
1. 학생 목록 페이지
전체 학생 목록을 한눈에 확인:
- 프로필 사진 및 이름
- 레벨 및 포인트
- 연속 출석일 (Streak)
- 역할 (Role) 뱃지
- 검색 기능 (이름 검색)
- 각 학생 카드 클릭 → 상세 진도 페이지 이동
2. 개별 학생 진도 페이지
학생 정보 헤더
- 프로필 사진
- 이름 (한국어 이름 우선 표시)
- 레벨 및 포인트
- 연속 출석일
- 가입일
통계 카드 (8개)
- 총 과제: 커뮤니티의 전체 과제 수
- 완료한 과제: 학생이 제출한 과제 수
- 과제 완료율: (완료한 과제 / 총 과제) × 100
- 과제 평균 점수: 제출한 과제의 평균 점수
- 총 퀴즈: 커뮤니티의 전체 퀴즈 수
- 완료한 퀴즈: 학생이 시도한 퀴즈 수
- 퀴즈 완료율: (완료한 퀴즈 / 총 퀴즈) × 100
- 퀴즈 평균 점수: 시도한 퀴즈의 평균 점수
탭 인터페이스
과제 탭
- 제출한 모든 과제 목록
- 각 과제별 정보:
- 과제 제목
- 점수 / 만점
- 상태 (채점 대기, 채점 완료)
- 제출 시간
- 채점 시간
- 과제 클릭 → 상세 보기
퀴즈 탭
- 시도한 모든 퀴즈 목록
- 각 퀴즈별 정보:
- 퀴즈 제목
- 점수 / 만점 (기본 100점)
- 완료 시간
- 퀴즈 클릭 → 상세 보기
일기 탭
- 작성한 일기 목록 (최근 10개)
- 각 일기별 정보:
- 일기 내용 미리보기 (첫 50자)
- 상태 (초안, 제출, 검토됨)
- 작성 시간
- 일기 클릭 → 상세 보기
출석 탭
- 출석 기록 목록
- 각 출석별 정보:
- 세션 코드
- 출석 시간
- 총 출석 횟수 표시
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]);
- 대소문자 구분 없음
- 이름으로 검색
- 실시간 필터링 (타이핑 즉시 반영)
사용 시나리오
일일 모니터링
- 학생 목록 페이지 접속
- Streak이 0인 학생 확인 (관심 필요)
- 해당 학생 클릭 → 상세 진도 확인
- 과제 완료율, 출석률 분석
- 필요 시 개별 상담 진행
학기말 평가
- 각 학생 상세 페이지 접속
- 과제 탭에서 전체 제출 현황 확인
- 퀴즈 탭에서 평균 점수 확인
- 통계 카드로 종합 성적 파악
- 성적표 작성 또는 피드백 제공
개별 상담 준비
- 상담 대상 학생 페이지 접속
- 일기 탭에서 최근 감정 상태 파악
- 출석 탭에서 참여도 확인
- 과제/퀴즈 탭에서 학습 수준 분석
- 맞춤형 학습 계획 수립
권한 관리
Owner & Admin
- 모든 학생의 진도 조회 가능
- 통계 데이터 접근 가능
- 개별 학생 상세 정보 확인 가능
Student
- 학생 목록 페이지 접근 불가
- 다른 학생 진도 조회 불가
- 본인 정보는 개인 대시보드에서 확인
성능 최적화
데이터 로딩
- 학생 목록은 한 번에 모두 로드 (일반적으로 50명 이하)
- 개별 진도는 memberId 기반으로 필요한 데이터만 조회
- 최근 10개 일기만 로드하여 응답 크기 최소화
쿼리 최적화
// 필요한 컬럼만 선택
.select({
memberId: communityMembers.id,
userId: users.id,
name: users.name,
nameKr: users.nameKr,
avatar: users.avatar,
})
캐싱
- 학생 목록은 5분 캐시 권장
- 개별 진도는 1분 캐시 권장 (실시간성 중요)
확장 가능성
향후 추가 기능
- 📊 학생 성적 추이 그래프
- 📅 학생별 학습 캘린더
- 📝 개별 학습 목표 설정
- 💬 학생에게 직접 메시지 발송
- 📈 학습 패턴 AI 분석
- 📤 개별 리포트 PDF 내보내기
- 🎯 맞춤형 과제 추천
- 🔔 저성취 학생 자동 알림
트러블슈팅
학생 목록이 비어있는 경우
- 커뮤니티에 학생이 등록되어 있는지 확인
- Owner/Admin 권한 확인
- 페이지 새로고침
통계가 0으로 표시되는 경우
- 실제로 과제/퀴즈가 없는지 확인
- 학생이 실제로 제출/시도를 했는지 확인
- API 응답 확인 (개발자 도구)
평균 점수가 이상한 경우
- 수동 채점이 완료되지 않은 과제 확인
- AI 채점 점수와 수동 점수 혼재 여부 확인
- 점수 계산 로직 확인 (manualScore 우선)
일기/출석이 표시되지 않는 경우
- 학생이 실제로 일기를 작성했는지 확인
- 출석 체크를 했는지 확인
- userId와 memberId 매핑 확인