글의 이전 버전을 남기는 것과 그 버전의 모든 파일을 계속 공개하는 것은 다른 일이다. 나는 현재 미디어 조회가 원고의 발행 상태와 버전을 함께 읽는 부분을 확인하고 그 조건을 독자가 바꿔 볼 수 있는 익명 판정 함수로 만들었다.

이전 개정의 참조와 현재 사용을 나눈다

원고를 수정하면 파일이 빠지거나 다른 자료로 바뀔 수 있다. 이전 개정은 복원 근거로 남길 수 있지만 현재 공개 본문과 같지는 않다. 실제 SQL은 원고 식별자뿐 아니라 현재 버전까지 참조 기록과 맞춘다. 예전 버전에 자료가 있었다는 사실을 현재 공개 사용으로 읽지 않도록 하는 조건이다.

새 모듈도 현재 원고를 하나씩 받고 참조의 버전과 비교한다. 같은 글의 현재 기록이 여러 개 들어오면 명시적으로 거절한다. 어느 기록이 정본인지 모르는 상태에서 우연히 먼저 찾은 값을 사용하는 방식은 피했다. 실제 저장소는 현재 원고를 고유하게 보존하고 개정 기록은 별도로 관리해야 한다.

파일 준비와 검토를 참조 앞에서 확인한다

현재 발행 글이 파일을 참조해도 그 파일이 준비되지 않았거나 검토되지 않았다면 일반 공개 읽기의 조건을 모두 갖춘 것은 아니다. 새 함수는 준비 상태와 실제 참인 검토 값을 먼저 확인한다. 그런 다음 현재 발행 원고의 참조를 찾는다. 문자열로 적힌 참이나 임의의 상태를 같은 승인 값으로 해석하지 않는다.

이 모듈은 익명 공개 읽기 조건만 계산한다. 관리자 인증이나 짧은 서명 미리보기는 별도 접근 경로다. 반환한 public이 거짓이라고 모든 관리 접근이 막혔다고 말하지 않는다. 파일이 저장되어 있는지와 일반 방문자에게 읽히는지, 검토자가 확인할 수 있는지를 다른 조건으로 남기는 이유다.

다른 발행 글이 쓰는 공유 파일을 함께 읽는다

하나의 그림이나 코드 파일을 여러 글에서 사용할 수 있다. 첫 글을 내렸다는 이유로 파일도 무조건 비공개가 되면 다른 글의 구현이 깨질 수 있다. 실제 SQL은 현재 발행 참조가 하나라도 있는지를 찾는다. 새 함수는 해당하는 원고 식별자 목록도 반환해 어떤 참조가 공개 판단을 유지하는지 읽을 수 있게 했다.

공개를 바꾸기 전에는 이 관계를 실제 관리 목록과 대조해야 한다. 예전 개정의 사용만 남았는지, 다른 발행 글이 현재 사용하는지에 따라 다음 작업이 달라진다. 새 예제는 한 글이 내려간 상태에서도 다른 글의 현재 참조를 켜서 결과를 비교한다. 원래 고객의 자료나 글 식별자는 넣지 않았다.

코드와 구현 살펴보기

현재 참조로 일반 공개 조건을 계산하기

export function currentMediaReference(media,entries,references){
 if(!media||typeof media.id!=='string'||!Array.isArray(entries)||!Array.isArray(references))throw new TypeError('Explicit media and current entries/references required');
 if(media.state!=='ready')return {public:false,reason:'not-ready',slugs:[]};
 if(media.reviewed!==true)return {public:false,reason:'review-required',slugs:[]};
 const current=new Map();
 for(const entry of entries){
  if(!entry||typeof entry.slug!=='string'||!entry.slug||!Number.isSafeInteger(entry.version)||entry.version<1||current.has(entry.slug))throw new TypeError('Unique current entries and positive versions required');
  current.set(entry.slug,entry);
 }
 const slugs=[...new Set(references.filter(reference=>{
  const entry=current.get(reference.slug);
  return reference.media_id===media.id&&entry?.status==='published'&&entry.version===reference.version;
 }).map(reference=>reference.slug))];
 return {public:slugs.length>0,reason:slugs.length?'current-published-reference':'no-current-published-reference',slugs,scope:'Anonymous public-read predicate only. Administrator access and expiring previews are separate; no deletion or recall of downloaded copies.'};
}

현재 SQL과 새 함수의 결과를 따로 대조한다

새 함수가 보기 좋아도 원래 저장소의 조건과 달라지면 재사용 예제로 오해를 만들 수 있다. 이번에는 실제 소스의 조회 SQL을 추출해 로컬 SQLite 메모리에서 실행했다. 이전 버전과 현재 버전, 초안과 내린 글, 공유 자료와 검토가 없는 상태, 참조가 제거된 조건 일곱 가지를 놓고 새 자바스크립트 함수와 결과를 비교했다.

이 일곱 조건은 원격 D1의 운영 데이터를 바꾸지 않고 검사했다. 새 함수는 이해를 돕는 공개 판정이며 SQL 트랜잭션이나 인증을 대신 구현하지 않는다. 데이터베이스 엔진과 코드에서 같은 결과가 나온 근거를 남기되 모든 운영 동시성이나 캐시 계층이 검증됐다고 넓히지 않는다.

버전을 바꾸는 예제로 공개 판단의 이유를 읽는다

아래 모형에서 현재 글의 버전은 둘로 두고 참조는 하나나 둘로 바꿀 수 있다. 글의 발행 상태와 자료 검토, 다른 글의 공유 참조도 함께 바꾼다. 반환한 이유와 참조 목록은 어떤 조건이 판단을 바꾸었는지 설명한다. 이 동작은 모형 안에만 남으며 실제 글과 파일의 공개 상태를 바꾸지 않는다.

새 브라우저의 조작 결과는 아직 검수하지 않았다. 실제 적용에서는 원고 저장과 현재 참조의 갱신, 미디어 응답을 이어서 확인해야 한다. 나는 복구를 위해 과거를 남기면서도 오늘 방문자가 받을 자료는 현재 버전의 조건으로 읽을 수 있는 모듈을 남기려 한다. 저장 이력과 공개 전달의 책임을 같은 기록으로 뭉개지 않는 방법이다.