세트리스트 수술: 구조화된 콘텐츠로 공연을 구하다
요약
Setlist Surgery는 공연 중 예기치 않은 상황(예: 베이시스트 취소) 발생 시, 곡 배열과 장비 간의 참조를 추적하여 실행 가능한 대체 세트를 제안하는 쇼 데스크 앱입니다. 이 도구는 남아 있는 시간 제한과 크루 구성에 맞춰 리허설된 최적의 공연 순서를 제공하며, 승인된 세트는 Sanity CMS에 저장됩니다.
핵심 포인트
- 공연 중 돌발 상황을 구조화된 콘텐츠로 관리하는 방법 제시
- 곡 배열 변경 시 영향을 받는 모든 요소를 추적 및 분석
- React/Next.js 기반으로 개발되었으며 Sanity CMS와 연동
이 글은 Sanity Challenge, Path Two: Vibe-Code Something Strange에 제출하는 내용입니다.
제가 만든 것
Setlist Surgery는 매우 특정한 최악의 저녁 상황을 위한 쇼 데스크입니다: 베이시스트가 취소되어 런닝 오더(running order)가 더 이상 작동하지 않는 경우입니다. 이 앱은 곡 배열, 공연자, 악기 간의 참조를 추적하여 어떤 노래들이 영향을 받는지 설명합니다. 남아 있는 크루와 장소의 시간 제한에 맞는 리허설된 배열을 제안합니다. 사용자가 대체할 곡을 선택하고, 리허설 준비 상태를 확인하며, 결과적인 세트를 승인합니다.
데모는 The Static Lines라는 가상의 밴드와 12개의 오리지널 곡 배열을 사용합니다. 라이선스 받은 녹음이나 가사는 없습니다. 베이시스트가 취소되면 예정된 6곡 중 3곡이 막힙니다. 이들을 Slow Motion, No Signal, Glasshouse로 대체하면, 변경 시간(changeovers)을 포함하여 40분 슬롯에 30:40 세트가 만들어집니다.
데모
시나리오를 시도하려면:
- 쇼를 초기화하고 베이시스트 취소를 선택합니다. 3곡에 주의가 필요합니다.
- Night Drive → Slow Motion, Static Bloom → No Signal, Neon Weather → Glasshouse로 교체합니다.
- 결과적으로 6/6 플레이 가능, 30:40의 런닝 오더와 9:20이 남는 것을 확인합니다.
- 리허설 확인을 선택한 다음, 세트 승인을 합니다. 새로고침하면: 승인된 세트는 Sanity에 저장되어 있습니다.
- 곡 순서를 재배열하면: 검토 화면은 초안(Draft)으로 돌아갑니다. 승인된 세트는 인쇄 보기(print view)도 노출합니다.

코드
앱은 React와 Next.js App Router를 사용하며 Vercel에 배포됩니다. 원래의 미리보기 버전은 Cloudflare Workers에서 Sites Vinext 빌드를 사용했습니다. 이 GitHub 저장소는 독립적인 Next.js 앱만 유지하고 해당 호스팅 스캐폴드(scaffold)는 제외합니다. lib/engine.ts가 적격성 및 검토 규칙을 소유하며, lib/show-service.ts가 세션 명령을 제한합니다. lib/sanity.server.ts는 GROQ와 개정본 보호(revision-guarded) 뮤테이션을 담당합니다. 스튜디오 스키마와 원래의 시드 스크립트도 포함되어 있습니다.
나의 빌드 프로세스
저는 Codex를 사용하여 이 과제를 구조화된 콘텐츠에 의존하는 작은 앱으로 만들었습니다. 작업은 도메인 엔진, Sanity 저장소, 전체 쇼 데스크, 그리고 검증/제출 증거로 구성되었습니다.
가장 유용했던 제약 조건은 적격성을 결정론적(deterministic)이고 설명 가능하게 만드는 것이었습니다. 노래 편곡은 누가 무엇이 필요한지 선언합니다. 참조 누락, 이용 불가능한 크루나 장비, 리허설되지 않은 편곡, 중복, 그리고 타이밍 위반 등이 준비 상태를 차단합니다.
저는 검토(review)를 콘텐츠 옆의 데이터로 모델링했습니다. 리허설과 승인은 실행 순서와 그 재료 요구 사항의 지문(fingerprint)에 연결됩니다. 나중에 소스 변경이 발생하면 아무도 세션을 편집하지 않았더라도 저장된 승인이 무효화될 수 있습니다. 이것이 바로 앱의 Draft → Rehearsal → Approved 상태 머신입니다.
실제 Sanity 프로젝트가 구성되자, 저는 실제 네트워크 쓰기 작업들을 검증했습니다: 취소(cancellation), 대체(replacements), 리허설, 승인, 다시 로드 지속성(reload persistence), 오래된 개정본 거부(rejection of an outdated revision), 그리고 재순서화 후 무효화(invalidation after a reorder). 별도의 검사에서 게시된 장소의 변경 시간(changeover)을 30초에서 31초로 임시 변경했습니다. 앱은 참조된 장소를 읽고 타이밍을 재계산한 다음, 승인을 무효화했습니다. 원래 값은 개정본 보호 기능을 통해 복원되었습니다. 호스팅된 브라우저는 그 후 30:40의 구조를 완료하고 다시 로드 후에도 승인을 유지했습니다.
Vercel에 정리된 GitHub 저장소를 배포한 후, 로그인 프롬프트 없이 라이브 HTTP 확인 및 브라우저 복구를 반복했습니다. 공개 배포는 세 가지 대체 항목을 모두 저장했으며 새로고침 후에도 'Approved' 상태를 유지했습니다. 위의 스크린샷은 해당 Vercel 검증에서 가져온 것입니다.
이 인터페이스는 숯색 쇼 데스크, 간결한 음악 메타데이터, 순서 타임라인, 그리고 크루 패널을 사용합니다. 데스크톱 및 휴대폰 레이아웃을 점검했으며, QA 과정에서 모바일 제어 레이블과 터치 영역을 수정했습니다. 전용 인쇄 스타일시트가 구현되었지만, 실제 인쇄/PDF 출력은 아직 캡처되지 않았습니다.
Sanity 프로젝트 상세 정보
- 프로젝트 ID:
raaqr2vc - 공개 데이터셋:
setlist_surgery - 위의 프로젝트 ID는 심사에서 요구하는 도전 과제의 프로젝트 세부 정보를 제공합니다.
노래 문서(Song documents)는 공연자 및 악기를 참조합니다. 쇼(Show)는 노래와 그 장소를 참조합니다. 장소(Venue)는 지속 시간과 변경 제약 조건을 제공합니다. 복구 세션 문서(Rescue session documents)는 참조 연결된 순서, 가용성 재정의, 검토 상태, 감사 기록을 저장합니다. 시드(seed)는 25개의 원래 카탈로그 문서를 생성하며 다시 실행해도 기존 기록을 보존합니다. 세션 문서는 사용 중에 별도로 생성됩니다.
서버는 GROQ를 통해 Content Lake를 읽고, 알려진 세션 명령만 수락하며, ifRevisionID로 패치하여 오래된 쓰기가 확정된 변경 사항을 덮어쓰지 못하도록 합니다. API 토큰은 호스팅 비밀(hosting secret)로서 서버 측에 남아 있습니다. 공개 데이터셋에는 가상의 데모 콘텐츠만 포함되어 있습니다.
문서 ID는 ss.* 네임스페이스를 사용합니다. Sanity는 심지어 공개 데이터셋에서도 마침표가 포함된 ID를 인증된 리더에게 제한합니다. 이는 익명 쿼리가 카탈로그 문서를 반환하지 않은 반면, 인증된 앱은 성공적으로 로드하는 것을 통해 확인되었습니다. 따라서 제출물은 프로젝트 ID를 제공하며, 검사 가능한 공개 카탈로그로 빈 쿼리 엔드포인트를 제시하지 않습니다. Sanity의 ID 및 경로 규칙를 참조하십시오.
에이전트 세션
소스에는 결정 및 수정 사항을 문서화한 빌드 저널과 검증 기록이 포함되어 있습니다. 공개 에이전트 세션 스크립트는 업로드되지 않았습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기