1. 파일 하나가 공개 주소가 되는 과정

이 사이트는 빌드 없이 HTML 파일을 Cloudflare Pages에 올립니다. 글을 추가할 때는 저장소 루트에 파일을 하나 만들고, 목록 페이지에서 그 파일에 해당하는 주소로 연결합니다. 예를 들어 지금 읽는 글의 파일은 note-cloudflare-static-routes.html입니다.

쭈니박스의 파일과 대표 공개 URL
배포 파일공개 URL 경로용도
index.html/홈
notes.html/notes제작 노트 목록
note-cloudflare-static-routes.html/note-cloudflare-static-routes이 글의 본문
404.html존재하지 않는 경로주소를 찾지 못했을 때 보여줄 안내

Pages는 HTML 확장자를 생략한 주소를 지원합니다. /notes.html로 요청하면 /notes로 이동하며, about/index.html 같은 디렉터리형 파일은 /about/ 형태를 사용합니다. 파일 이름을 바꾸기 전에 공개 주소도 함께 바뀌는지 확인해야 하는 이유입니다. Cloudflare의 경로 매칭 설명에서 이 동작을 확인할 수 있습니다.

여기서는 소스 파일을 바로 찾기 쉽도록 평면 파일과 확장자 없는 링크를 선택했습니다. 다른 사이트가 디렉터리형 주소를 쓴다고 잘못된 것은 아닙니다. 후행 슬래시를 붙이기 위한 리디렉션 하나만으로 검색 색인 실패나 광고 심사의 원인을 단정할 수도 없습니다. 선택한 대표 주소를 내부 링크와 메타데이터에서 일관되게 쓰는 것이 점검할 부분입니다.

2. canonical, 리디렉션, 404는 서로 다른 일을 합니다

주소를 정리할 때 혼동하기 쉬운 세 가지
장치뜻이 사이트의 예
canonical같거나 비슷한 내용의 대표 URL을 검색엔진에 알립니다. 방문자를 다른 페이지로 이동시키지는 않습니다.이 글의 대표 주소는 /note-cloudflare-static-routes
301·308 리디렉션서버가 Location 헤더로 이동할 주소를 알립니다. 브라우저가 새 주소를 요청합니다.www 호스트에서 대표 호스트로 이동
404 응답요청한 주소의 콘텐츠가 없다고 알립니다. 안내 화면은 별도로 제공할 수 있습니다.없는 글 주소에서 사용자 정의 404 화면 표시

이 글의 HTML <head>에는 다음 선언이 있습니다. 다른 글은 자기 본문의 주소를 넣어야 합니다. 모든 글에서 홈을 선언하면 서로 다른 글까지 같은 문서의 변형이라고 알리는 셈이 됩니다.

<link rel="canonical"
      href="https://jjunybox.com/note-cloudflare-static-routes" />

내부 링크와 사이트맵에도 같은 대표 주소를 씁니다. 확인용 쿼리 ?review=20260910는 글 내용을 바꾸지 않으므로 이 사이트의 canonical에는 넣지 않습니다. 반대로 쿼리에 따라 실제 내용이 달라지는 사이트라면 별도로 판단해야 합니다. 대표 주소 선언은 Google의 선택에 주는 신호이며, 색인 명령이나 보장이 아닙니다. Google의 canonical 안내도 사이트맵·내부 링크·대표 URL이 서로 모순되지 않도록 권장합니다.

3. 없는 페이지에는 홈 대신 404를 돌려줍니다

2026년 8월 30일 사전 조사에서는 없는 주소에서 홈 HTML과 200 응답이 나왔습니다. 방문자는 홈이 열린 것으로 볼 수 있지만, 해당 주소의 글이 있는지 없는지가 불명확해집니다. 페이지가 없는데 정상 응답으로 전달하는 상태는 soft 404의 원인이 될 수 있습니다.

현재 저장소는 루트에 404.html을 두고 Pages의 기본 처리를 사용합니다. 최상위 404.html이 없는 Pages 프로젝트에는 기본 SPA 폴백이 적용될 수 있습니다. 정적 문서 사이트라면 이 파일이 실제 배포 대상에 포함됐는지 먼저 확인합니다. Pages의 Not Found·SPA 동작을 함께 참고할 수 있습니다.

이 저장소에는 현재 _redirects 파일이 없습니다. 404를 만들기 위해 이 파일에 임의의 404 rewrite 규칙을 추가할 필요도 없습니다. Cloudflare는 _redirects의 404 rewrite를 지원하지 않는다고 명시합니다. Pages Functions가 요청을 처리한다면 그 요청에는 _redirects가 적용되지 않으므로 함수 응답을 따로 확인해야 합니다. Cloudflare Redirects의 지원 범위를 기준으로 사용 중인 방식부터 구분합니다.

404 화면의 문구만 바꾸어서는 상태 코드가 바뀌지 않습니다. 없는 경로를 실제로 요청해 404인지 확인하고, 응답 본문도 없는 주소 안내인지 확인해야 합니다. Google도 오류 화면을 200으로 전달하는 경우를 soft 404의 사례로 설명합니다. Google의 HTTP 상태 코드 설명에서 정상 응답과 오류 응답의 처리 차이를 볼 수 있습니다.

4. PowerShell에서 세 가지 응답을 직접 읽습니다

Windows의 시작 메뉴 → PowerShell 검색 → Windows PowerShell을 엽니다. 아래 명령은 공개 URL을 조회하므로 프로젝트 폴더로 이동하지 않아도 됩니다. PowerShell의 별칭과 혼동하지 않도록 curl.exe라고 입력합니다.

대표 URL의 상태와 콘텐츠 형식

curl.exe -sS -o NUL -D - "https://jjunybox.com/notes"

-D -는 응답 헤더를 화면에 출력하고 -o NUL은 내려받은 본문을 버립니다. 요청 방식은 GET입니다. 정상 목록 페이지라면 상태 코드가 200이고 Content-Type에 text/html이 포함돼야 합니다. 헤더 이름의 대소문자나 HTTP 버전은 환경에 따라 다를 수 있습니다.

www가 경로와 쿼리를 보존하는지 확인

curl.exe -sS -o NUL -D - "https://www.jjunybox.com/notes?review=20260910"

첫 응답의 301 또는 308과 Location: https://jjunybox.com/notes?review=20260910을 확인합니다. 목적지가 홈으로 바뀌면 글의 경로가 사라진 것이고, 쿼리가 없으면 전달하려던 값이 빠진 것입니다. 처음에는 리디렉션을 따라가는 -L을 넣지 않아야 첫 응답을 구분하기 쉽습니다. 목적지를 확인한 뒤 같은 명령에 -L을 더하면 이동 과정과 마지막 응답까지 볼 수 있습니다.

없는 주소의 상태와 본문을 따로 확인

curl.exe -sS -o NUL -D - "https://jjunybox.com/__review_missing_20260910"
curl.exe -sS "https://jjunybox.com/__review_missing_20260910"

첫 명령은 상태가 404인지 확인하는 용도입니다. 두 번째 명령은 본문을 출력합니다. 홈의 소개 글 대신 없는 주소를 안내하는 HTML이 있어야 합니다. 나중에 같은 이름의 파일을 만들었다면 새로운 없는 경로로 바꾸어 검사합니다.

200이라고 나온 페이지의 실제 정체 확인

curl.exe -sS "https://jjunybox.com/note-cloudflare-static-routes" |
  Select-String -Pattern 'canonical', '<title', '<h1'

결과에 이 글의 제목과 대표 주소가 나타나는지 읽습니다. 200이어도 제목이 홈이거나 canonical이 https://jjunybox.com/이면 다른 문서를 받은 것일 수 있습니다. 제목 외에 글에만 있는 본문 문장을 직접 검색하면 공통 템플릿만 내려온 경우도 구분할 수 있습니다.

5. 2026년 9월 10일의 실제 확인 결과

아래는 해당 날짜에 공개 사이트의 일부 주소를 GET으로 확인한 결과입니다. 8월 30일 기록에 남았던 없는 주소의 200 응답과 www의 200 응답은 이 표본에서 재현되지 않았습니다.

2026년 9월 10일 공개 응답 표본
요청확인한 응답
jjunybox.com/200, 홈 HTML
jjunybox.com/notes200, 제작 노트 목록 HTML
jjunybox.com/note-cloudflare-static-routes200, 해당 글의 HTML
jjunybox.com/__review_missing_20260910404, 사용자 정의 없는 주소 안내
www.jjunybox.com/notes?review=20260910301, 같은 경로와 쿼리를 보존한 jjunybox.com 주소로 이동

이 결과는 위 주소들의 응답 기록입니다. 사이트의 모든 경로, 모든 접속 환경 또는 Google의 실제 수집 결과를 확인했다는 뜻은 아닙니다. HTTP 응답이 올바른 것과 글이 독자에게 충분한 가치를 주는 것도 별도 문제이며, 이 검사로 광고 심사 승인을 예측할 수는 없습니다.

별도 사례: 미리보기는 성공했는데 운영에서는 404였습니다

같은 날 새 배포 보안 글을 확인했을 때, 작업 브랜치의 미리보기에서는 글이 열렸지만 본도메인에서는 404였습니다. 배포 성공 표시만 보면 놓칠 수 있는 차이입니다. 이 시점에는 작업 브랜치가 운영 브랜치에 병합되지 않았으므로, 미리보기와 운영이 서로 다른 버전을 제공하고 있었습니다.

2026년 9월 10일 운영 병합 전 표본 — 동일한 /note-ai-release-safety 경로
확인 대상상태글의 고유 제목판단
작업 브랜치 미리보기200응답 HTML에 있음미리보기에 새 글이 반영됨
본도메인 운영 배포404응답에 없음운영에는 아직 반영되지 않음

여기서 해결할 일은 모든 404를 홈으로 돌리는 규칙을 추가하는 것이 아닙니다. 없는 글을 404로 응답한 동작 자체는 맞습니다. 의도한 콘텐츠 버전이 운영 배포에 포함됐는지 확인하는 것이 먼저입니다. 이 표는 과거 확인 시점의 기록이며, 이후 병합·배포가 끝나면 운영에서도 해당 글과 200 응답이 나오는 것이 기대 결과입니다.

  1. Cloudflare → Workers & Pages → 프로젝트 → Deployments에서 Production과 Preview를 구분하고 각각의 커밋을 확인합니다.
  2. 두 배포의 같은 경로를 GET으로 요청해 상태 코드와 본문의 고유 문장 하나를 비교합니다. 사이트 공통 이름은 판별 표식으로 쓰지 않습니다.
  3. 의도한 커밋이 운영에 없으면 먼저 병합·배포 대상을 확인합니다. 운영 커밋이 맞는데 본문이 다를 때 캐시와 별도 라우팅 규칙을 조사합니다.

확인 내용을 공유할 때는 위 표처럼 환경 종류, 경로, 상태와 제목 포함 여부만 남겨도 판단할 수 있습니다. 계정 이메일이 보이는 대시보드 캡처나 전체 응답 헤더를 공개할 필요는 없습니다. 프리뷰 주소가 비밀이라는 뜻은 아니지만, 증명에 필요하지 않은 내부 식별자는 이 기록에서 생략했습니다.

6. 결과가 다르면 파일, 배포, 외부 규칙 순서로 확인합니다

로컬 파일을 수정한 것과 운영 사이트에 반영된 것은 다릅니다. Cloudflare 대시보드에서 Workers & Pages → 해당 Pages 프로젝트 → Deployments로 들어가 확인 중인 배포가 성공했는지, 의도한 변경을 포함한 배포인지 먼저 살펴봅니다.

  • 있는 글이 404: 파일 이름의 철자·대소문자, 배포 출력 위치, 실제 배포된 파일을 확인합니다.
  • 없는 글이 홈과 함께 200: 배포 루트의 404.html 존재 여부와 전체 경로를 홈으로 보내는 폴백을 확인합니다.
  • www에서 계속 200: HTML의 canonical과 별개로 호스트 리디렉션이 실제 적용됐는지 확인합니다.
  • 리디렉션이 반복: 후행 슬래시 또는 호스트를 서로 반대 방향으로 보내는 규칙이 겹쳤는지 확인합니다.
  • 상태는 맞는데 본문이 다름: 요청 URL, 배포 버전, 캐시된 응답과 본문의 고유 문장을 함께 비교합니다.

로컬 미리보기에도 경계가 있습니다. 예를 들어 Python의 기본 http.server는 Pages의 확장자 없는 URL 변환이나 Cloudflare의 호스트 리디렉션을 그대로 재현하지 않습니다. 로컬에서 /notes.html의 모양을 확인해도 배포된 /notes의 동작까지 검사한 것은 아닙니다. 화면은 로컬에서 보고, 공개 주소의 상태와 이동은 배포 URL에서 따로 확인합니다.

한 글을 새로 게시할 때는 본문 파일, 목록의 링크, canonical, 사이트맵에 적은 URL을 한 묶음으로 점검하면 빠진 부분을 찾기 쉽습니다. 이전 주소가 외부에 공유돼 있었다면 주소 변경을 파일명 변경만으로 끝내지 말고, 이전 글과 새 글의 대응 관계도 기록합니다.

참고 자료와 적용 범위

이 글은 쭈니박스의 빌드 없는 정적 HTML 구조를 예제로 합니다. 다른 서비스의 SPA, Pages Functions 또는 서버 렌더링에 그대로 적용하기 전에는 요청을 실제로 처리하는 계층을 확인해야 합니다. 아래 공식 문서는 2026년 9월 10일 확인했습니다.

상태 코드뿐 아니라 본문이 처음부터 전달되는지 확인하는 이유는 초기 HTML에 본문을 담는 이유에 정리했습니다. 실제 변경 기록은 업데이트에서 확인할 수 있습니다.

제작 노트 목록으로 돌아가기