강의 서비스
이 페이지는 lumie-backend/modules/lecture를 다룹니다.
책임
lecture 모듈은 다음을 소유합니다.
- 강의 레코드와 메타데이터
- 강의 가시성 상태
- 학생 접근을 위한 강의-반 타기팅
- 학생에게 보이는 강의 목록과 watch payload
- 강의 ID 또는 class 기준 강의 조회를 위한 소규모 internal API
소스 경로
| Path | 역할 |
|---|---|
lumie-backend/modules/lecture/src/main/java/com/lumie/lecture/adapter/in/web | 공개 lecture 및 student lecture controller |
lumie-backend/modules/lecture/src/main/java/com/lumie/lecture/adapter/in/internal/LectureServiceAdapter.java | internal monolith API 구현 |
lumie-backend/modules/lecture/src/main/java/com/lumie/lecture/application/service | command 및 query service |
lumie-backend/modules/lecture/src/main/java/com/lumie/lecture/domain/entity | Lecture, LectureClassTarget |
lumie-backend/libs/internal-api/src/main/java/com/lumie/lecture/api/LectureService.java | internal lecture 조회 계약 |
lumie-backend/app/src/main/resources/db/migration/public/V18__rls_baseline.sql | baseline lectures table |
lumie-backend/app/src/main/resources/db/migration/public/V57__create_lecture_class_targets.sql | lecture_class_targets 도입 및 cross-module no-FK 경계 문서화 |
공개 인터페이스
| Surface | Entrypoints |
|---|---|
| Lecture CRUD | POST /v1/lectures, GET /v1/lectures, GET /v1/lectures/{id}, PATCH /v1/lectures/{id}, DELETE /v1/lectures/{id} |
| Student listing | GET /v1/lectures/student/class/{classId} |
| Student watch payload | GET /v1/lectures/student/{id}/watch |
내부 인터페이스
LectureService는 다음을 export합니다.
- ID 기준 단일 lecture 조회
- class 기준 lecture의 page 조회
classId와classIds를 모두 포함하는 응답 형태
중복된 classId와 classIds field는 두 개의 별도 비즈니스 개념이 아니라,
모듈의 현재 저장 모델을 반영합니다.
집계와 테이블
| Aggregate | Table | 참고 |
|---|---|---|
Lecture | lectures | teacher, title, description, YouTube URL, visibility, lecture date, legacy primary class_id 저장 |
LectureClassTarget | lecture_class_targets | 강의의 학생 가시 class target 전체를 저장 |
V57__create_lecture_class_targets.sql의 migration comment가 핵심 schema
경계입니다. class_id는 의미상 class 모듈을 참조하지만, lecture와 classroom은
별도 모듈 경계이므로 데이터베이스는 의도적으로 foreign key를 강제하지
않습니다.
런타임 흐름
학생에게 보이는 강의 접근
핵심 동작
- instructor 사용자는 자신에게 배정된 class의 lecture만 관리할 수 있습니다.
LectureVisibility.STUDENT는 최소 하나의 class target을 요구합니다.- 학생용 lecture 목록은
lectureRepository.findVisibleByTargetClassId(...)를 사용하므로, 단순한lectures.class_id가 아니라 target row가 가시성을 결정합니다. - 학생 watch 접근은 다음 둘 다를 확인합니다.
- lecture가 학생에게 공개되어 있는가
- 현재 student가 target class 중 하나 이상에 등록되어 있는가
- write 시
class_id는 primary 또는 fallback class로 유지되고, 전체 집합은lecture_class_targets에 저장됩니다.
의존성과 경계
| Dependency | 존재 이유 |
|---|---|
StaffService | 인증된 user에서 현재 instructor의 staff ID 해석 |
ClassService | class target과 student enrollment visibility 검증 |
StudentService | watch 접근을 위한 현재 student ID 해석 |
실패 모드
- 존재하지 않는 lecture 또는 class는
LECTURE_NOT_FOUND,CLASS_NOT_FOUND로 실패합니다. - target이 없는 student visibility는
STUDENT_VISIBILITY_REQUIRES_CLASS로 실패합니다. - target class 집합 밖의 학생은
LECTURE_NOT_VISIBLE_TO_CLASS를 받습니다. - 배정되지 않은 class의 lecture를 관리하려는 instructor는
FORBIDDEN을 받습니다.
알아둘 계약상 미묘한 차이
lecture targeting은 의도적으로 migration 상태에 있습니다.
lectures.class_id는 여전히 존재하며 primary/fallback class로 사용됩니다.lecture_class_targets는 학생 접근을 위한 authoritative multi-class visibility table입니다.
현재 코드는 둘 다 읽고 쓰므로, 문서도 둘 다 설명합니다.