같은 송출 키로 방송을 다시 시작했을 때, 종료한 재생목록에 새 파일을 붙이면 될까요. 이미 종료 표시를 본 플레이어는 새 파일을 기다리지 않을 수 있습니다. 반면 새로 들어온 플레이어는 추가된 목록을 읽습니다. 주소는 같아도 두 시청자의 해석이 달라지는 문제입니다.

저는 종료한 목록은 유지하고 새 회차에 새 URL을 주는 방향으로 설계했습니다. 짧게 재개한 방송에서 과거 구간을 이어 보여 줄지는 주소 재사용과 분리하고, 300초 이내·init 호환 등의 계승 조건으로 판단합니다. 기존 플레이어에 알린 종료를 뒤집지 않으면서 새 시청자에게 필요한 창을 만드는 방식입니다.

이 글은 발행 계층의 연결이 남은 진행 중 설계입니다. 목록 렌더 부품은 병합됐지만 전체 발행·재기동 조합의 종단 검증까지 완료된 것은 아닙니다. 설계·검증은 AI와 협업했으며, 종료의 의미와 계승 조건은 제가 정했습니다.

서로 다른 세 식별자를 한 값으로 쓰지 않기

송출 키는 같은 스트리머가 다시 쓸 수 있습니다. 녹화기의 mtxi StreamID도 논리 회차를 그대로 나타내지 않습니다. 빠른 재접속이나 녹화기 재시작만으로 한 회차 안에서 표식이 바뀔 수 있기 때문입니다. 처음의 “녹화기 표식이 바뀌면 새 방송”이라는 가정을 수정했습니다.

구분 맡기는 의미 그대로 회차 ID로 쓰기 어려운 이유
송출 경로·키 수신할 방송 경로 여러 회차에서 재사용 가능
녹화기 mtxi 표식 녹화기 연결·기록의 변화 신호 같은 회차의 재접속에도 변경 가능
논리 회차 사용자가 이어서 볼 방송 단위 훅과 DB 장부로 판단해야 함

세 값을 분리한 뒤 회차 판정은 훅과 DB 장부를 가진 사이드카에 맡기고 녹화기 표식은 보조 신호로 쓰도록 했습니다. 그러면 송출 키를 그대로 쓰면서도 새 회차를 만들 수 있고, 반대로 녹화기 표식이 바뀌어도 같은 회차의 재접속으로 다룰 수 있습니다. 식별자의 변화와 사용자가 보는 방송의 종료가 반드시 같은 사건은 아니기 때문입니다.

ENDLIST를 지우는 대신 새 회차를 만듭니다

ENDLIST는 해당 목록에 더는 미디어 조각이 추가되지 않음을 나타냅니다. RFC 8216의 ENDLIST 정의가 전달하는 의미를 유지하려면, 이미 닫았다고 알려 준 목록을 다시 여는 동작을 피하는 편이 명확했습니다.

클라이언트가 알아야 할 고정 진입점은 유지하되 그 진입점에서 현재 회차의 목록 URL을 받도록 설계했습니다. 새 회차가 열리면 새 주소를 반환하고, 예전 주소의 ENDLIST는 지우지 않습니다. 이미 종료를 본 플레이어와 새 방송을 보러 온 플레이어가 같은 파일의 서로 다른 상태를 기대하지 않게 하는 것입니다.

이 방식에는 회차를 찾는 진입점과 새 URL을 해석하는 과정이 추가됩니다. 주소 하나를 계속 수정하는 편의보다 종료 의미를 유지하는 쪽을 택한 대가입니다.

여기에는 다른 종류의 경합도 있습니다. 이전 작업자가 늦게 쓰거나 종료 발행이 일반 발행과 경쟁하는 문제는 URL만 바꾼다고 사라지지 않습니다. DB를 기준으로 한 세대·권한 설계가 따로 필요한 이유입니다.

짧게 다시 켠 방송의 과거 구간은 어떻게 할까

목록 URL을 새로 만드는 것과 되감기 내용을 모두 버리는 것은 같은 결정이 아닙니다. 짧은 재개에는 이전 회차 조각을 새 목록의 초기 접두부로 계승하는 규칙을 뒀습니다. 다만 시간만 가깝다고 붙이면 코덱 설정이 다른 조각이 섞일 수 있어 init 호환성도 확인합니다.

이전 회차 상태와 재개 조건 설계한 처리
종료 뒤 300초 이내, init 호환 등 조건 충족 새 목록에서 제한된 이전 조각 계승
시간 조건 초과 오래된 방송 꼬리를 새 창에 붙이지 않음
init 비호환 새 창을 시작
기존 목록에 ENDLIST 있음 기존 목록은 그대로 유지

300초는 설계한 계승 조건입니다. 오래전 방송의 꼬리가 새 되감기 창에 붙는 것을 막기 위한 수명 제한으로, 복구 시간이나 사용자 대기 실측값은 아닙니다. 시간 조건만 맞아도 init이 다르면 계승하지 않습니다. 렌더 부품에서 지원하는 계승 범위는 PR #196의 제약을 따릅니다.

새 목록을 만드는 쪽으로 복잡도를 모았습니다

이 선택은 예전 목록을 열었다 닫는 복잡도를 줄이지만, 접두부·여러 init·불연속 누계의 책임을 없애지는 않습니다. 창에서 옛 조각을 축출할 때 누적 불연속 번호가 바뀌지 않도록, 렌더와 경계 계산이 같은 규칙을 써야 합니다. 최근 1시간을 구성하는 경계도 계승한 조각과 현재 조각을 함께 고려해야 합니다.

목록의 문법과 창 경계는 PR #196에서 독립 부품으로 병합됐습니다. 900조각 기대 목록을 독립 생성기와 대조하고 여러 hls.js 파서에서 구문 오류를 확인한 것은 그 부품의 근거입니다. 이것만으로 실제 S3 발행과 모든 회차 전이가 완성됐다고 말할 수는 없습니다. 전체본 30–31쪽은 설계와 구현 상태를 나눠 표시합니다.

종료된 목록을 다시 열지 않는 대신, 새 목록을 어떻게 시작할지에 복잡도를 모았습니다. 같은 송출 키를 쓸 수 있다는 사실은 유지하면서 목록의 수명은 회차 URL로 나누고, 되감기 구간의 연속성은 계승 조건으로 처리하는 설계입니다. 다음 단계는 이 규칙을 S3 발행·종료 전이·재기동에 연결해, 기존 주소가 닫힌 상태로 남고 새 주소만 갱신되는지 검증하는 것입니다.


이 글은 PokeClip의 개발·검증 기록을 2026년 10월 15일 기준으로 정리한 CASE 26입니다. 전체 기술 기록에서 연결되는 결정을 함께 읽을 수 있습니다.