홈페이지 제작 중에 자료가 비어 있다는 말은 생각보다 모호하다. 그 기능이 필요 없다는 뜻일 수도 있고, 담당자가 아직 파일을 보내지 않았다는 뜻일 수도 있다. 둘을 같은 빈칸으로 처리하면 필요 없는 메뉴가 남거나, 확인해야 할 내용을 조용히 빼고 홈페이지를 올릴 수 있다.

내가 정리한 교체형 템플릿은 자료를 confirmed, absent, pending으로 나눈다. 현재 빌드 소스에는 미확인 자료를 공개 배포 전에 막는 조건과 자료가 없는 메뉴를 제외하는 흐름이 있다. 또 확정된 메뉴라도 실제 항목이 비어 있으면 거부한다. 나는 이 차이를 자료를 전달하는 사람과 구현하는 AI가 같이 이해할 수 있도록 작은 모듈로 풀어 썼다.

작은 화면으로 살펴보기

이 예시는 구조를 설명하는 분리된 데모다. 실제 화면·동작을 검증한 범위는 본문에 남긴다.

나는 자료가 없는 이유부터 남긴다

확정은 공개할 내용과 자료를 확인했다는 상태다. 없음은 그 자료를 사용하지 않는다고 정한 상태다. 확인 중은 필요한지 또는 어떤 자료인지 아직 판단이 끝나지 않은 상태다. 없음과 확인 중이 모두 빈 화면으로 보인다고 해서 같은 결정은 아니다.

예를 들어 사진 메뉴가 필요 없다고 확정하면 메뉴와 연결된 첫 화면 소개를 함께 빼야 한다. 반면 사진을 받는 중이라면 작업 목록에 기다리는 자료로 남겨야 한다. 이를 AI가 임의의 사진이나 이전 프로젝트 자료로 채우면 빈칸은 없어져도 근거 없는 홈페이지가 된다. 나는 상태를 설명 없이 자동으로 확정으로 바꾸지 않는다.

미리보기 가능과 공개 가능을 나누었다

모든 자료가 오기 전에도 전체 흐름을 검토할 필요는 있다. 내 원본의 미리보기 조건은 일부 미확인 상태를 허용하고 공개 배포 조건은 이를 막는다. 이것은 빈칸을 고객에게 공개해도 된다는 뜻이 아니라, 내부 검토와 실제 공개에 서로 다른 기준을 둔다는 뜻이다.

새 모듈도 previewReady와 releaseReady를 별도로 반환한다. 확인 중인 자료가 있으면 내부 검토 계획을 만들 수 있지만 공개 준비는 끝난 것으로 표시하지 않는다. 내부 미리보기는 실제로 비공개 접근을 갖추어야 한다. 변수 이름에 preview가 있다고 인증이나 검색 제외가 자동으로 생기는 것은 아니다.

확정이라는 표시보다 실제 내용을 먼저 확인한다

상태를 확정으로 바꾸는 것만으로 자료가 생기지는 않는다. 원본 테스트에는 확정된 메뉴의 자료 목록이 비어 있으면 빌드를 거부하는 경우가 있다. 나는 담당자가 상태를 바꿨더라도 실제 항목과 연결을 같이 확인하는 조건을 남긴다.

여기서 새 예시는 비어 있지 않은 자료 참조 문자열을 검사한다. 그 파일이 존재하는지, 공개 권한이 있는지, 이미지 안에 다른 이름이 있는지는 이 함수가 확인하지 않는다. 실제 제작 프로그램에는 경로·파일·자료 종류·공개 범위 검사를 이어 붙여야 한다. 데이터 형태 검사를 자료의 진실성 확인으로 설명하지 않는다.

연결된 소개도 같이 사라지거나 같이 준비되어야 한다

자료 메뉴를 뺐는데 첫 화면의 자세히 보기 버튼은 남으면 방문자는 없는 페이지로 들어간다. 반대로 첫 화면 소개는 확정인데 연결될 상세 자료는 확인 중이면 발행된 것처럼 보이는 소개가 앞서 나갈 수 있다. 원본 빌드는 확정된 홈 영역에 연결되는 확정 메뉴가 있는지도 확인한다.

작은 모듈에서는 requires로 한 영역이 요구하는 다른 영역을 명시했다. 상세 자료가 확정된 경우에만 그 소개를 공개 대상으로 삼을 수 있다. 실제 프로젝트에서는 메뉴 링크와 카드, 관련 글, 다운로드, 사이트맵까지 같은 상태를 따라야 한다. 이 예시는 한 단계 의존성 계획을 검사하는 함수이며 복잡한 경로 생성기 전체를 대체하지 않는다.

나는 상태 판단을 한 함수로 모았다

다음 코드는 새로 작성한 설명용 구현이다. 각 영역의 필수 여부와 상태를 확인하고 공개할 영역, 기다리는 영역, 제외할 영역, 오류를 나누어 반환한다. 자료가 아예 입력되지 않은 경우는 확인 중으로 남긴다. 모르는 상태나 오타로 생긴 영역은 조용히 무시하지 않는다.

선택 자료는 없음으로 제외할 수 있지만 필수 자료는 없음으로 처리해도 공개 준비가 되지 않는다. 필요한 정보를 아직 받지 못한 상황과, 홈페이지 목적에 필요한 정보를 사용하지 않겠다고 정한 상황은 다른 논의가 필요하기 때문이다. 필수 여부는 이 예시의 규칙 입력이며 모든 홈페이지에 같은 항목을 강요하지 않는다.

코드와 구현 살펴보기

JavaScript · 자료 상태로 미리보기와 발행 계획을 나누는 모듈

export function planPublication(rules, records) {
  if (!rules || !records || typeof rules !== 'object' || typeof records !== 'object' ||
      Array.isArray(rules) || Array.isArray(records)) {
    throw new TypeError('Rules and records must be objects');
  }
  const ids = Object.keys(rules);
  if (!ids.length) throw new TypeError('At least one section rule is required');
  const visible = [], pending = [], omitted = [], errors = [];
  for (const id of Object.keys(records)) {
    if (!Object.hasOwn(rules, id)) errors.push(`${id}: unknown section`);
  }
  for (const id of ids) {
    const rule = rules[id];
    if (!rule || typeof rule.required !== 'boolean' ||
        (rule.requires !== undefined && !Array.isArray(rule.requires))) {
      throw new TypeError(`${id}: invalid section rule`);
    }
    const record = Object.hasOwn(records, id) ? records[id] : { status: 'pending' };
    if (!record || !['confirmed', 'absent', 'pending'].includes(record.status)) {
      errors.push(`${id}: invalid material status`);
      continue;
    }
    if (record.status === 'pending') { pending.push(id); continue; }
    if (record.status === 'absent') {
      omitted.push(id);
      if (rule.required) errors.push(`${id}: required material is absent`);
      continue;
    }
    if (!Array.isArray(record.items) || !record.items.length ||
        record.items.some(item => typeof item !== 'string' || !item.trim())) {
      errors.push(`${id}: confirmed material needs nonempty item references`);
      continue;
    }
    visible.push(id);
  }
  for (const id of ids) {
    for (const dependency of rules[id].requires || []) {
      if (!Object.hasOwn(rules, dependency)) {
        errors.push(`${id}: unknown dependency`);
      } else if (visible.includes(id) && !visible.includes(dependency)) {
        errors.push(`${id}: confirmed section lacks its confirmed dependency`);
      }
    }
  }
  return {
    visible, pending, omitted, errors,
    previewReady: errors.length === 0,
    releaseReady: errors.length === 0 && pending.length === 0
  };
}

export function assertRelease(plan) {
  if (!plan.releaseReady) throw new Error('Resolve material states before release');
  return [...plan.visible];
}

확인 중인 자료를 남긴 적용 예시

다음 합성 예시는 소개 자료만 확정됐고 문서 자료는 확인 중인 상태다. 내부 검토 계획은 만들 수 있어도 공개를 확인하는 assertRelease는 오류를 낸다. 자동 빌드에서는 공개 파일 생성과 업로드 전에 이 조건을 실행하는 방식으로 연결할 수 있다.

어떤 자료를 확정할지는 함수가 대신 결정하지 않는다. 실제 내용의 검토 근거와 확인한 시점은 내부 장부에 남기고 상태를 바꾼다. 예시의 자료 참조는 식별용 문자열이며 실제 고객의 파일이나 이름이 아니다. 상태 변경과 근거 기록을 연결하면 나중에 왜 메뉴가 빠졌는지도 확인할 수 있다.

코드와 구현 살펴보기

JavaScript · 내부 검토는 가능하지만 공개는 멈추는 합성 자료

const rules = {
  introduction: { required: true },
  documents: { required: false },
  documentTeaser: { required: false, requires: ['documents'] }
};
const records = {
  introduction: { status: 'confirmed', items: ['approved-introduction'] },
  documents: { status: 'pending' },
  documentTeaser: { status: 'absent' }
};

const plan = planPublication(rules, records);
// plan.previewReady === true
// plan.releaseReady === false
// plan.pending contains 'documents'
// Render only confirmed sections in an INTERNAL preview.
// Display plan.pending as review notes; do not treat it as public approval.
assertRelease(plan); // throws: unresolved material blocks release

나는 정상 발행뿐 아니라 멈추는 경우도 확인했다

새 모듈에는 합성 데이터로 검사한 아홉 가지 흐름을 남겼다. 선택 자료 제외, 미확인 차단, 누락을 미확인으로 처리, 필수 자료 없음, 확정된 빈 목록, 미준비 연결, 정상 연결, 잘못된 상태와 영역, 입력 보존을 확인했다. 모두 통과했지만 이것은 실제 파일과 화면, API 권한, 클라우드 배포 검사와 다른 범위다.

실제 템플릿의 과거 검수와 현재 읽은 소스는 더 넓은 빌드 조건의 근거다. 그렇더라도 이 글의 함수만 가져와 파일 검토와 공개 접근 설정까지 완료됐다고 판단하지 않는다. 나는 어떤 조건이 자동으로 막히고 어떤 조건은 사람과 AI가 자료를 읽어 확인해야 하는지를 따로 남긴다.

  1. 없음은 사용하지 않기로 확인한 상태이며 확인 중과 구별되는가.
  2. 필수 자료가 없거나 확정 내용이 비면 공개를 멈추는가.
  3. 메뉴를 뺄 때 연결된 소개와 링크도 같은 상태를 따르는가.
  4. 자료 파일의 존재와 권한, 내용 검토는 별도로 수행하는가.
  5. 미리보기는 비공개이고 공개 준비와 다른 표시를 갖는가.
  6. 마지막 상태 변경의 이유와 확인 근거를 찾을 수 있는가.

나는 비어 있는 화면보다 끝나지 않은 판단을 관리한다

자료가 없는 부분을 예쁘게 채우는 일은 쉽다. 그러나 홈페이지가 실제 내용을 설명해야 한다면 채우기보다 기다리고 제외하고 확인하는 선택이 먼저다. 빈칸은 디자인 문제일 수도 있지만 그보다 먼저 결정이 끝났는지를 보여주는 표시일 수 있다.

나는 자료 상태를 관리하는 작은 규칙이 반복 제작의 품질을 지킨다고 생각한다. 다음 홈페이지에서도 무엇을 빼도 되는지, 무엇을 기다려야 하는지, 어떤 확인이 있어야 공개할 수 있는지를 남기면 AI와 함께 작업해도 판단의 근거가 사라지지 않는다.