성적에 넣지 않는 과제도 제출할 할 일은 남는다
“성적 미반영 학습 활동” 표시 옵션을 켤 때마다 과제를 적재하고, 끌 때 지운다면 표시 선택 하나가 할 일 데이터 전체를 다시 만드는 조건이 된다. LearningX의 초기 구현은 제출 유형 not_graded·none을 이 옵션에 따라 제외 목록에서 빼는 방식이었다. 하지만 제출 방식과 최종 성적 반영 여부는 다른 속성이다.
변경은 성적 미반영 과제의 정의를 omit_from_final_grade = true이면서 grading_type <> not_graded인 과제로 바꿨다. 정상 제출 유형을 가진 과제는 기존 적재 경로로 유지하고, 이미 만들어진 할 일에 배지를 붙일지 옵션으로 결정한다.
| 과제 조건 | 적재 | 옵션 ON | 옵션 OFF |
|---|---|---|---|
| 정상 제출 유형, 최종 성적 포함 | 기존 조건대로 | 성적 미반영 배지 없음 | 배지 없음 |
| 정상 제출 유형, 최종 성적 제외, 평가 유형 있음 | 기존 조건대로 | 성적 미반영 배지 | 배지 없음 |
| 제출 유형 not_graded·none | 기존 제외 조건 유지 | 옵션으로 적재하지 않음 | 적재하지 않음 |
평가 유형 not_graded도 배지 대상에서 제외한다. 제출을 계기로 완료하는 과제 경로와 맞지 않기 때문이다. “성적에서 제외했다”는 이유만으로 제출할 수 없는 모든 과제를 할 일에 넣는 변경은 아니다.
화면에서 달리 보여줄 일을 다시 저장할 이유가 사라졌다
배지 조회는 옵션이 켜졌을 때만 이미 적재된 과제 ID를 대상으로 성적 미반영 조건을 확인한다. 옵션이 꺼지면 배지 대상은 빈 집합이다. 할 일 행 자체의 존재는 이 선택에 따라 바뀌지 않는다.
// 이미 적재된 과제 중 배지를 붙일 대상만 찾는다.
Assignment::whereIn('id', $assignmentIds)
->where('omit_from_final_grade', true)
->where('grading_type', '<>', 'not_graded')
->pluck('id'); 이에 따라 옵션 토글에서 과제의 StudentAssignmentInfo 재계산 잡을 대량으로 보내던 호출을 제거했다. 주기적으로 누락된 성적 미반영 과제를 찾아 보충하던 함수도 삭제했다. 쿼리를 더 빠르게 실행하는 방법에 앞서, 표시 정책 때문에 필요했던 적재·삭제·보정 경로 자체가 없어졌다.
과제와 연결되지 않은 미평가 퀴즈·토론은 별도의 완료 판정 경로를 가진다. 이 항목들은 옵션을 켤 때 재적재하고 끌 때 정리하는 큐 처리를 유지한다. 배지로 해결한 과제의 정책을 모든 학습 활동에 똑같이 적용하지 않았다.
완료를 다시 확인하지 않는 선택에는 제품 규칙이 들어 있다
남은 퀴즈·토론의 주기적 재계산에는 skipCompleted = true를 전달한다. 기존 할 일을 먼저 읽어 미완료·미적재 항목이 있는 학생만 제출 상태를 조회하고, 이미 활성 상태로 완료된 항목은 갱신을 건너뛴다. 새 학생의 할 일을 채우거나 새 제출로 미완료를 완료로 바꾸는 경로는 남는다.
- 기존 할 일 확인
컴포넌트·학생별 기존 행과 완료 상태를 읽는다.
- 미완료와 누락만 판정
필요한 학생의 퀴즈 제출·토론 댓글 존재를 조회한다.
- 기존 완료 유지
주기 경로는 완료를 되돌리지 않는다. 구조 변경 리스너는 기본값 false로 제목·기간도 갱신한다.
완료는 주기 재계산에서 단조롭게 유지한다는 정책이다. 회귀 테스트는 완료 뒤 제출 행을 삭제해도 완료 상태가 남도록 기대한다. 제출 취소나 댓글 삭제가 할 일을 미완료로 되돌려야 하는 제품이라면 이 규칙을 그대로 사용할 수 없다. 단순히 “변하지 않은 값을 건너뛴다”는 설명만으로는 이 비용이 드러나지 않는다.
남은 조회를 좁혀도 실행 계획의 효과는 따로 확인해야 한다
완료 판정에는 제출 본문 전체가 필요하지 않으므로 퀴즈·학생 또는 토론·학생의 distinct 쌍만 읽는다. 주기 대상 과목을 찾는 쿼리를 위해 assignment_id IS NULL인 행에 (item_type, course_id) 부분 인덱스도 추가했다. 대상 조건에 맞는 인덱스 사용을 가능하게 하는 변경이다.
인덱스는 CONCURRENTLY로 생성하고 마이그레이션의 트랜잭션 감싸기를 끈다. 생성 중 접근을 고려한 선택이지만, 인덱스 생성 시간·공간과 이후 쓰기 유지 비용은 남는다. 이 정의만으로 실제 실행 계획에서 순차 스캔이 사라졌거나 처리 시간이 특정 비율로 줄었다고 단정할 수는 없다.
관련 테스트는 옵션 ON/OFF의 배지 차이, 성적 포함 과제와 평가 없음 제외, 정상 제출 과제의 옵션과 무관한 적재, 신규 할 일 보충과 완료 유지 규칙을 검사한다. 검증 대상은 데이터와 표시 정책의 관계다. 실제 대규모 과목의 큐 처리량이나 인덱스 IO 효과를 측정한 결과와는 구분해야 한다.