VitePress 사이트를 Cloudflare Pages + Access로 비공개 배포하기
VitePress Cloudflare 배포날짜: 2026-04-25 작성자: 최원재 관련 도구/언어: Node.js, VitePress, Wrangler, Cloudflare Pages, Cloudflare Access
목적
로컬에서 작성하는 VitePress 기반 연구노트를 나만 볼 수 있는 비공개 웹사이트로 만들어, 어디서든(맥/아이패드/모바일) 접속 가능하게 한다.
요구사항:
- 어디서든 접속 (외부망 포함)
- 완전 비공개 (URL을 알아도 본인만 접근 가능)
- 무료
선택한 스택: Cloudflare Pages (정적 호스팅) + Cloudflare Access (이메일 인증 게이트).
환경
| 항목 | 값 | 비고 |
|---|---|---|
| OS | macOS | - |
| Node.js | LTS | npm 포함 |
| 정적 사이트 생성기 | VitePress 1.6.x | - |
| 배포 CLI | Wrangler 3.x | Cloudflare 공식 CLI |
| 호스팅 | Cloudflare Pages | 무료 |
| 접근 제어 | Cloudflare Access (Zero Trust Free) | 50명까지 무료 |
전체 흐름
- Wrangler 설치 (devDependency)
- 빌드 통과 확인 (
npm run build) - Cloudflare 가입 및 이메일 인증
wrangler login→npm run deploy로 첫 배포- Zero Trust 대시보드에서 Access Application + 정책 추가
- 시크릿 창에서 접근 검증
1. Wrangler 설치 및 deploy 스크립트
package.json에 dev dependency와 deploy 스크립트를 추가한다.
{
"scripts": {
"dev": "vitepress dev docs",
"build": "vitepress build docs",
"preview": "vitepress preview docs",
"deploy": "npm run build && wrangler pages deploy docs/.vitepress/dist --project-name=research-notes"
},
"devDependencies": {
"vitepress": "^1.6.3",
"markdown-it-mathjax3": "^4.3.2",
"wrangler": "^3.90.0"
}
}설치:
npm install왜 Direct Upload 방식인가
GitHub 저장소 없이 로컬 빌드 결과물(docs/.vitepress/dist/)을 바로 업로드하는 방식. Git 워크플로우 없이도 배포 가능.
2. 빌드 통과 시키기 (dead link 처리)
npm run build 실행 시 dead link가 있으면 빌드가 실패한다. VitePress는 마크다운 내부 링크의 유효성을 검사한다.
자주 만나는 패턴 3가지:
(a) Placeholder 링크: 템플릿에 [제목](./링크) 같은 더미 링크가 남아있는 경우 → 링크 문법을 제거하거나 실제 경로로 교체.
(b) 대소문자 불일치: macOS는 case-insensitive지만 빌드 결과물은 대소문자를 보존하므로 배포 후 404 발생 가능 → 마크다운 내 링크와 실제 파일명의 대소문자를 정확히 일치.
(c) 빈 폴더 가리키는 링크: /projects/DataNDT처럼 폴더 안에 index.md가 없는 경우 → 실제 문서 파일(/projects/datandt)로 교체.
ignoreDeadLinks 옵션은 신중히
config.js에 ignoreDeadLinks: true를 넣으면 검사 자체가 꺼진다. 편하지만 진짜 깨진 링크를 놓치게 되므로 가능한 한 실제 링크를 고치는 쪽이 안전.
빌드 성공 확인 후 다음 단계로.
3. Cloudflare 계정 준비
- https://dash.cloudflare.com 가입
- 이메일 인증 메일 클릭 (반드시 필요)
이메일 인증 안 하면 발생하는 에러
배포 시 다음 에러로 막힌다:
✘ [ERROR] A request to the Cloudflare API (...) failed.
Your user email must been verified [code: 8000077]해결: 받은편지함 + 스팸함에서 noreply@notify.cloudflare.com 발신 메일의 verify 링크 클릭. 메일이 없으면 https://dash.cloudflare.com/profile 에서 재발송.
4. 첫 배포
# 로그인 (브라우저 자동 오픈, 1회)
npx wrangler login
# 배포
npm run deploy처음 실행 시 "Project ... not found. Would you like to create it?" → Yes. Production branch는 기본값(main) 그대로.
배포 완료 시 출력 예:
✨ Deployment complete!
🌎 https://abc12345.research-notes.pages.dev두 종류의 URL
- Production URL:
https://research-notes.pages.dev— 항상 최신 배포를 가리킴 - Preview URL:
https://<해시>.research-notes.pages.dev— 특정 배포 시점을 영구 보존
평소엔 Production URL만 쓰면 됨.
프로젝트명은 전 세계 유일해야 함
notes처럼 흔한 이름은 이미 선점되어 있어 Cloudflare가 자동으로 notes-29z 같은 랜덤 접미사를 붙인다. 본인이 원하는 이름을 그대로 쓰려면 wchoi-notes 등 충분히 고유한 이름을 선택.
이 시점에는 사이트가 전 세계 공개 상태다. 다음 단계에서 잠근다.
5. Cloudflare Access로 잠그기
Cloudflare Access는 메인 대시보드(dash.cloudflare.com)가 아닌 Zero Trust 대시보드(one.dash.cloudflare.com)에서 설정한다.
5-1. 팀 생성
https://one.dash.cloudflare.com 접속 → 팀 이름(team subdomain) 임의 지정 (예: wchoi-notes). 플랜 선택 화면에서 Free 선택.
Free 플랜 카드 등록
Cloudflare가 결제 카드 정보를 요구하지만, Free 플랜은 실제 과금되지 않는다 (정책상 등록만 받음).
5-2. Application 추가
Access → Applications → Add an application → Self-hosted
설정값:
- Application name:
research-notes(임의) - Application domain:
research-notes.pages.dev(배포된 Production URL의 도메인) - Session duration: 원하는 기간 (1 month 권장 — 너무 짧으면 자주 재인증)
5-3. 정책 추가
Add a policy:
- Policy name:
myself - Action:
Allow - Include → Emails → 본인 이메일 (예:
wjc.kriss@gmail.com)
저장하면 즉시 적용된다.
6. 작동 확인
시크릿 창에서 https://research-notes.pages.dev 접속 (기존 창은 이미 Cloudflare에 로그인된 상태라 테스트 부정확).
기대 흐름:
- Cloudflare Access 로그인 페이지 자동 리다이렉트
- 본인 이메일 입력 → 6자리 원타임 코드 발송
- 코드 입력 → 사이트 정상 로딩
안 되는 경우 체크리스트
| 증상 | 원인 |
|---|---|
| 로그인 없이 사이트가 바로 열림 | Application domain 오타 |
| 즉시 "Access denied" | 정책에 본인 이메일 등록 누락 |
| 인증 메일 안 옴 | 스팸함 (noreply@notify.cloudflare.com) |
| 무한 리다이렉트 | 쿠키 충돌 → 시크릿 창 사용 |
아이패드/모바일에서도 동일한 URL로 접속, 같은 이메일 코드 플로우. 사파리에서 인증 후 홈 화면에 추가하면 앱처럼 사용 가능.
7. 일상 워크플로우
내용 업데이트:
# .md 파일 수정 후
npm run deploynpm run deploy는 자동으로 npm run build를 먼저 실행한다. Access 설정은 그대로 유지되므로 별도 작업 불필요.
관찰 사항
Direct Upload의 장점
- GitHub 저장소가 필요 없어 Google Drive 같은 클라우드 동기화만으로도 워크플로우 유지 가능
- 빌드를 로컬에서 하므로 Cloudflare 빌드 환경 의존성 이슈가 없음
Direct Upload의 단점
- 빌드를 로컬에서 해야 하므로 Node.js 환경이 없는 곳에서는 업데이트 불가
- 여러 사람이 동시에 작업하기엔 Git 연동 방식이 더 적합
보안 주의
- 옛 Pages 프로젝트(예: 이름을 바꿔서 새로 만든 경우 옛 이름의 프로젝트)는 반드시 삭제. 안 그러면 Access 미적용 상태로 공개되어 있음
- Cloudflare Access는 도메인 단위로 적용되므로, 같은 사이트를 여러 도메인에서 서비스하면 모든 도메인에 정책 적용 필요
TODO
- [ ] 커스텀 도메인 연결 (선택)
- [ ] 정기 백업 (Cloudflare는 호스팅만 담당, 원본은 로컬/Drive에 있음)
참고
관련 노트
- 관련 노트 제목
다음 단계: 커스텀 도메인 연결, 빌드 자동화