Cloudflare Pages 로 정적 사이트 굴리기
정적 사이트를 Cloudflare Pages 에 올리는 일 자체는 십 분이면 끝납니다. 문제는 그 다음입니다. git push 는 배포의 시작이지 끝이 아닌데, 그걸 모르면 올라가지 않은 것을 올라갔다고 착각하게 됩니다.
이 문서는 위키와 작업일지 두 사이트를 한 저장소에서 올리며 겪은 것을 정리한 것입니다.
한 저장소에 사이트가 여럿일 때
섹션 제목: “한 저장소에 사이트가 여럿일 때”저장소 하나에 프로젝트가 여럿이면 두 가지를 잡아야 합니다.
| 설정 | 값 | 없으면 |
|---|---|---|
| Root directory | wiki |
저장소 루트를 빌드하려다 실패 |
| Build watch paths | wiki/* |
다른 프로젝트만 고쳐도 매번 다시 빌드 |
Root directory 는 프로젝트를 만들 때 정합니다. Build watch paths 는 Settings → Builds 에 따로 있고 기본값이 * 라서, 놓치면 옆 프로젝트를 고칠 때마다 이쪽도 빌드가 돕니다. 빌드 시간은 유료 계정에서 한도가 있으니 그냥 낭비입니다.
빌드 환경 고정
섹션 제목: “빌드 환경 고정”Node 버전은 프로젝트마다 기본값이 다르고, 오래된 기본값이 걸리면 설치 단계에서 멈춥니다. 루트 디렉터리에 .node-version 을 두면 됩니다.
22.17.0Astro 7 은 Node 22.12 이상을 요구합니다. 요구 버전은 node_modules/<패키지>/package.json 의 engines 에서 확인하십시오.
커스텀 도메인
섹션 제목: “커스텀 도메인”같은 Cloudflare 계정의 zone 이면 Custom domains 에서 도메인만 넣으면 CNAME 이 자동으로 생깁니다. 직접 만들지 마십시오.
_headers 와 _redirects
섹션 제목: “_headers 와 _redirects”빌드 결과 폴더(dist/)의 루트에 두면 Pages 가 읽습니다. public/ 에 두면 빌드가 복사해 주므로 그것도 됩니다. 다만 빌드 때 만들어지는 것은 dist/ 에 직접 써야 합니다.
/* Content-Security-Policy: ... X-Content-Type-Options: nosniff X-Frame-Options: DENY Referrer-Policy: strict-origin-when-cross-origin
/_astro/* Cache-Control: public, max-age=31536000, immutable내용 해시가 파일 이름에 붙는 산출물(/_astro/*, 폰트)만 장기 캐시를 걸어야 합니다. HTML 에 걸면 글을 고쳐도 한참 옛 화면이 나갑니다.
리다이렉트는 이렇게 씁니다.
/ /ko/ 302/ko/old-path/ https://blog.example.com/posts/new/ 301목적지에 다른 도메인의 전체 주소를 써도 됩니다. 글을 다른 사이트로 옮길 때 옛 주소를 끊지 않는 방법입니다.
push 는 배포의 끝이 아닙니다
섹션 제목: “push 는 배포의 끝이 아닙니다”여기가 핵심입니다.
Pages 빌드가 실패해도 이전 버전이 계속 200 을 돌려줍니다. 그래서 주소를 두드려 200 을 세는 것으로는 배포됐는지 알 수 없습니다. 실패한 배포와 성공한 배포가 똑같이 200 입니다.
빌드가 자기 커밋을 결과물에 남기게 하면 대조할 수 있습니다.
// 빌드 뒤에 돈다const commit = process.env.CF_PAGES_COMMIT_SHA || gitHead()await writeFile('dist/build-id.txt', commit)CF_PAGES_COMMIT_SHA 는 Pages 가 빌드 환경에 넣어 주는 값입니다. 그러면 검증은 이렇게 됩니다.
dist/build-id.txt를 라이브에서 읽는다- 로컬
HEAD와 같아질 때까지 기다린다 - 같아진 뒤에야 경로와 헤더를 확인한다
기다리지 않고 바로 확인하면 옛 버전을 검사하고 통과시킵니다.
무엇을 확인해야 하나
섹션 제목: “무엇을 확인해야 하나”200 만 세지 마십시오. 화면이 200 을 주면서 알맹이만 사라지는 고장이 실제로 흔합니다.
- 경로를 이름으로 확인합니다. 목록을 두고 하나씩 두드립니다. 문서를 늘리면 목록도 같이 늘립니다.
- 없는 주소가 404 인지 봅니다. 200 을 주면 검색엔진이 빈 페이지를 색인합니다.
- 소유확인 파일과 색인 키 파일이 살아 있는지 봅니다. 사라져도 화면은 멀쩡하고, 몇 달 뒤 유입이 끊긴 뒤에야 알게 됩니다.
- 보안 헤더가 실제로 붙는지 봅니다.
_headers가 배포물에 안 들어가면 조용히 사라집니다.
| 함정 | 증상 | 대응 |
|---|---|---|
| Build watch paths 기본값 | 남의 폴더 고쳐도 빌드 | <폴더>/* 로 좁힘 |
| 감시 경로를 좁힌 뒤 | 검증이 멀쩡한 배포를 실패로 | 커밋이 아니라 폴더 변경 여부를 봄 |
| DNS 음성 캐시 | 브라우저만 못 찾음 | 캐시 비우기, 다른 곳에서 확인 |
| 빌드 실패 | 여전히 200 | build-id 대조 |
| 원문 grep 검사 | 안 보이는 문자열에 걸림 | 있는 것을 셈 |
