본문으로 건너뛰기

반 서비스

이 페이지는 lumie-backend/modules/class를 다룹니다. Gradle 모듈 이름은 class이지만, Java package와 internal API는 classroom을 사용합니다.

책임

class 모듈은 다음을 소유합니다.

  • 반(class) 레코드
  • 반 시간표 패턴
  • 학생 enrollment와 enrollment 상태
  • 교사용 및 학생용 반 목록
  • 반 dashboard 지표
  • attendance, lecture, assignment, student deletion 흐름이 사용하는 internal classroom lookup 계약

소스 경로

Path역할
lumie-backend/modules/class/src/main/java/com/lumie/classroom/adapter/in/web공개 class, enrollment, statistics controller
lumie-backend/modules/class/src/main/java/com/lumie/classroom/adapter/in/internal/ClassServiceAdapter.javainternal monolith API 구현
lumie-backend/modules/class/src/main/java/com/lumie/classroom/application/servicecommand, query, statistics service
lumie-backend/modules/class/src/main/java/com/lumie/classroom/domain/entityClassEntity, ClassEnrollment
lumie-backend/modules/class/src/main/java/com/lumie/classroom/domain/vo/SchedulePattern.javaJSONB schedule 모델
lumie-backend/libs/internal-api/src/main/java/com/lumie/classroom/api/ClassService.javainternal class 계약
lumie-backend/app/src/main/resources/db/migration/public/V18__rls_baseline.sqlbaseline classes, class_enrollments table

공개 인터페이스

SurfaceEntrypoints
Class CRUDPOST /v1/classes, GET /v1/classes, GET /v1/classes/{id}, PATCH /v1/classes/{id}, DELETE /v1/classes/{id}
Role-oriented listsGET /v1/classes/teacher/{teacherId}, GET /v1/classes/student/{studentId}
Enrollment managementGET /v1/classes/{classId}/enrollments, POST /v1/classes/{classId}/enrollments, PATCH /v1/classes/{classId}/enrollments/{enrollmentId}, DELETE /v1/classes/{classId}/enrollments/{enrollmentId}, DELETE /v1/classes/{classId}/enrollments/student/{studentId}
DashboardGET /v1/classes/statistics/dashboard

내부 인터페이스

ClassService는 다음을 export합니다.

  • ID 기준 class 조회
  • teacher, student, 전체 class에 대한 pagination
  • class의 enrolled student ID
  • 주어진 student 집합의 enrolled class row
  • student enrollment 여부 확인
  • 활성 enrollment 여부 확인과 활성 enrollment 일괄 drop
  • 특정 staff의 assigned class 여부 확인

여러 모듈이 class 소유권과 enrollment 상태에 의존하기 때문에, 이 internal API는 백엔드에서 가장 넓은 범위의 API 중 하나입니다.

집계와 테이블

AggregateTable참고
ClassEntityclassesteacher_id, teacher_deleted, schedule_pattern, description 저장
ClassEnrollmentclass_enrollments(class_id, student_id) unique 제약과 drop/completion timestamp 추적

ClassEntity.schedulePattern은 custom attribute converter를 통해 JSONB로 저장됩니다. 따라서 class 모듈이 teaching schedule overlap 검증의 source of truth입니다.

런타임 흐름

일정 확인이 포함된 등록 흐름

핵심 동작

  • teacher ID는 class 생성 전에 StaffService.getStaff(...)로 검증합니다.
  • teacher schedule overlap은 해당 teacher의 기존 모든 class를 기준으로 검사합니다.
  • student schedule overlap은 enrollment 전에 그 student의 현재 ENROLLED class 전부와 비교합니다.
  • teacher_deleted는 staff row가 사라진 뒤에도 삭제된 teacher placeholder를 렌더링할 수 있도록 class row에 남아 있습니다.
  • enrollment 상태 전이는 aggregate 내부에서 구현됩니다.
  • ENROLLED -> DROPPED
  • ENROLLED -> COMPLETED
  • student 삭제는 internal API의 dropActiveEnrollmentsForStudent(...)에 의존합니다.

대표 계약 예시

이 예시는 EnrollStudentsRequest, ClassEnrollmentResponse, ClassEnrollmentControllerTest.enrollStudents_returns201, ClassCommandService의 overlap guard와 일치합니다.

POST /v1/classes/1/enrollments

{
"studentIds": [42, 43]
}
[
{
"id": 10,
"classId": 1,
"studentId": 42,
"enrolledAt": "2026-06-14T09:00:00Z",
"droppedAt": null,
"status": "ENROLLED",
"createdAt": "2026-06-14T09:00:00Z",
"updatedAt": "2026-06-14T09:00:00Z"
},
{
"id": 11,
"classId": 1,
"studentId": 43,
"enrolledAt": "2026-06-14T09:00:00Z",
"droppedAt": null,
"status": "ENROLLED",
"createdAt": "2026-06-14T09:00:00Z",
"updatedAt": "2026-06-14T09:00:00Z"
}
]

한 학생이 이미 시간이 겹치는 다른 ENROLLED class를 갖고 있으면, 같은 endpoint는 409 Conflict와 함께 GlobalExceptionHandler의 RFC 7807 body를 반환합니다.

{
"type": "urn:lumie:error:class-011",
"title": "Student already has a class at the overlapping time",
"status": 409,
"detail": "Student 42 already has class '수학 심화반' at overlapping time",
"instance": "/v1/classes/1/enrollments",
"code": "CLASS_011"
}

의존성과 경계

Dependency존재 이유
StaffServiceteacher record를 검증하고 해석

class 모듈은 teacher나 student 데이터를 소유하지 않습니다. ID만 저장하고, teacher 이름이나 유효성을 확인해야 할 때 staff 모듈에 질의합니다.

실패 모드

  • 존재하지 않는 class, teacher, enrollment는 각각 CLASS_NOT_FOUND, TEACHER_NOT_FOUND, ENROLLMENT_NOT_FOUND로 실패합니다.
  • enrollment 쓰기는 DUPLICATE_ENROLLMENT, SCHEDULE_OVERLAP, STUDENT_SCHEDULE_OVERLAP로 실패할 수 있습니다.
  • schedule_pattern의 JSON 직렬화/역직렬화 실패는 JSON_SERIALIZATION_FAILED로 surface됩니다.

관측성

  • command service는 create, update, delete, enroll, drop 작업을 로그합니다.
  • query service는 teacher가 없을 때 전체 응답을 실패시키지 않고 "삭제된 강사" fallback으로 해석합니다.
  • 이 모듈은 동기식 בלבד입니다. 현재 class 쓰기 surface에는 event, queue, scheduled repair loop가 없습니다.

검증

./gradlew :modules:class:test
./gradlew :app:test --tests '*Class*'
cd lumie-document/docusaurus && npm run build

예상 성공 신호:

  • Gradle이 BUILD SUCCESSFUL로 끝납니다.
  • ClassEnrollmentControllerTestClassCommandServiceTest가 실패 없이 통과합니다.
  • Docusaurus가 backend/class-svc에 대해 MDX 또는 broken-link 오류 없이 완료됩니다.

관련 페이지