← 목록
기타 2026-07-12 4KB 읽기 4분

crowny-class 레슨-영상 배선 API (wire/unwire/wire-status)

개요

lesson 모듈(modules/lesson/routes.js)에 레슨↔영상 배선 3엔드포인트 추가. 커리큘럼 레슨 72건(week1~20, 유료)에 영상을 붙이는 관리자 도구. 페이월 가드(유료레슨+무료영상 조합 차단)가 이 작업의 보안 핵심.

무엇을 했는지

1. POST /api/lesson/wire (admin)

{lessonId, videoId} → 레슨.videoId 저장 + 영상.lessonId 역참조 저장 + video.free = (lesson.free === true) 강제 동기화.
  • 레슨 없음 → 404, 영상 없음 → 404
  • video.cvfStatus === 'error' → 400 거부
  • video.cvfStatus === 'encoding' → 409
  • 통과 시 {ok, lessonId, videoId, free} 응답

2. POST /api/lesson/unwire (admin)

{lessonId} → lesson.videoId 제거 + 해당 영상의 lessonId도 제거(양방향, 역참조 일치 확인 후). {ok} 응답.

3. GET /api/lesson/wire-status (admin)

{lessons:[{id,week,title,videoId,free}], readyVideos:[{id,title,cvfStatus,free,lessonId}]} — 레슨은 week 정렬(기존 loadCurriculum() 재사용), readyVideos는 cvfStatus 'ready' 또는 레거시 무status만 후보로.

페이월 가드 (보안 핵심)

video.free = (lesson.free === true) 를 wire 시점에 항상 재계산해 저장. 무료 레슨에 물린 영상만 free=true가 될 수 있고, 유료 레슨(커리큘럼 72건)에 물리는 순간 영상은 자동으로 free=false로 강등된다. 기존에 free=true였던 영상도 유료 레슨에 배선되면 즉시 false로 덮어써짐(실측 확인 — 아래 검증 참조).

라우팅 순서

동적 라우트 /api/lesson/<id>[/sub] 매칭보다 앞에 wire/unwire/wire-status를 명시적으로 배치(curriculum/seed와 동일 패턴). validId()wire/unwire/wire-status 예약어 추가해 향후 라우트 재배치 시에도 레슨 id로 오인되지 않도록 방어.

관련 파일

  • /Users/ef/crowny-class/modules/lesson/routes.js — wire/unwire/wire-status 3엔드포인트 + validId/validRef
  • /Users/ef/crowny-class/한선씨/배선판정.한선 — 신규. 배선가능판정() 4상(티=ok/옴=인코딩중409/타=거부400/음=없음404) + 상태코드매핑() + free동기화() + 언와이어영상대상(). 컴파일·실행 검증 완료(테스트() 8케이스 전부 기대값 일치).
  • /Users/ef/crowny-class/API-CONTRACT.md — 계약 원본(수정 안 함, 이미 명시돼 있던 계약을 구현)

검증

  • node --check routes.js → 통과
  • 실데이터 스모크(w01l1 레슨 + mrgilkb817j8 영상, 백업/복원 방식으로 라이브 데이터 훼손 없이 검증):
1. wire 정상 케이스 → 200, video.free가 기존 true(레거시 무료 영상)에서 false로 강등됨(레슨.free가 true가 아니므로) — 페이월 가드 실동작 확인 2. wire 레슨없음 → 404 3. wire 영상없음 → 404 4. wire admin 없이 → 401 5. wire-status → lessons 95건 week정렬, readyVideos 23건, w01l1이 videoId/free 반영해 목록에 나타남 6. unwire → 200, 양방향 videoId/lessonId 모두 제거 확인 7. unwire 레슨없음 → 404
  • 테스트 후 두 데이터 파일(데이터/레슨/w01l1.json, 데이터/영상/mrgilkb817j8.json)을 원본으로 diff 복원 확인
  • 한선씨/배선판정.한선hanseonc_high 컴파일 성공(2310 큐브) + crownyc run 실행, 4상 판정·상태코드매핑·free동기화·언와이어대상 전부 기대값과 일치
  • 준수사항

    • class.html/admin.html/video 모듈 미침범 (lesson/routes.js만 수정)
    • 라이브 서버 재기동 안 함(Integrate 담당 몫으로 남김)

    잔여 이슈

    • 프론트(admin.html) 배선 UI는 별도 작업 — 이 API 계약을 소비하는 화면 구현 필요
    • video 모듈 /api/video/list는 무로그인 시 free 영상만 노출하므로, wire로 free가 false로 바뀐 영상은 무로그인 미리보기 목록에서 자동으로 빠짐(기존 게이트 로직과 자연스럽게 정합)

    크라우니코드

    lookup HIT 0건 / MISS 1건(레슨영상배선판정4상 — 신규 생성) / learn 추가 1건