Skip to content

VitePress 사이트를 Cloudflare Pages + Access로 비공개 배포하기

VitePress Cloudflare 배포

날짜: 2026-04-25 작성자: 최원재 관련 도구/언어: Node.js, VitePress, Wrangler, Cloudflare Pages, Cloudflare Access


목적

로컬에서 작성하는 VitePress 기반 연구노트를 나만 볼 수 있는 비공개 웹사이트로 만들어, 어디서든(맥/아이패드/모바일) 접속 가능하게 한다.

요구사항:

  • 어디서든 접속 (외부망 포함)
  • 완전 비공개 (URL을 알아도 본인만 접근 가능)
  • 무료

선택한 스택: Cloudflare Pages (정적 호스팅) + Cloudflare Access (이메일 인증 게이트).

환경

항목비고
OSmacOS-
Node.jsLTSnpm 포함
정적 사이트 생성기VitePress 1.6.x-
배포 CLIWrangler 3.xCloudflare 공식 CLI
호스팅Cloudflare Pages무료
접근 제어Cloudflare Access (Zero Trust Free)50명까지 무료

전체 흐름

  1. Wrangler 설치 (devDependency)
  2. 빌드 통과 확인 (npm run build)
  3. Cloudflare 가입 및 이메일 인증
  4. wrangler loginnpm run deploy로 첫 배포
  5. Zero Trust 대시보드에서 Access Application + 정책 추가
  6. 시크릿 창에서 접근 검증

1. Wrangler 설치 및 deploy 스크립트

package.json에 dev dependency와 deploy 스크립트를 추가한다.

json
{
  "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"
  }
}

설치:

bash
npm install

왜 Direct Upload 방식인가

GitHub 저장소 없이 로컬 빌드 결과물(docs/.vitepress/dist/)을 바로 업로드하는 방식. Git 워크플로우 없이도 배포 가능.

npm run build 실행 시 dead link가 있으면 빌드가 실패한다. VitePress는 마크다운 내부 링크의 유효성을 검사한다.

자주 만나는 패턴 3가지:

(a) Placeholder 링크: 템플릿에 [제목](./링크) 같은 더미 링크가 남아있는 경우 → 링크 문법을 제거하거나 실제 경로로 교체.

(b) 대소문자 불일치: macOS는 case-insensitive지만 빌드 결과물은 대소문자를 보존하므로 배포 후 404 발생 가능 → 마크다운 내 링크와 실제 파일명의 대소문자를 정확히 일치.

(c) 빈 폴더 가리키는 링크: /projects/DataNDT처럼 폴더 안에 index.md가 없는 경우 → 실제 문서 파일(/projects/datandt)로 교체.

ignoreDeadLinks 옵션은 신중히

config.jsignoreDeadLinks: true를 넣으면 검사 자체가 꺼진다. 편하지만 진짜 깨진 링크를 놓치게 되므로 가능한 한 실제 링크를 고치는 쪽이 안전.

빌드 성공 확인 후 다음 단계로.

3. Cloudflare 계정 준비

  1. https://dash.cloudflare.com 가입
  2. 이메일 인증 메일 클릭 (반드시 필요)

이메일 인증 안 하면 발생하는 에러

배포 시 다음 에러로 막힌다:

✘ [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. 첫 배포

bash
# 로그인 (브라우저 자동 오픈, 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에 로그인된 상태라 테스트 부정확).

기대 흐름:

  1. Cloudflare Access 로그인 페이지 자동 리다이렉트
  2. 본인 이메일 입력 → 6자리 원타임 코드 발송
  3. 코드 입력 → 사이트 정상 로딩

안 되는 경우 체크리스트

증상원인
로그인 없이 사이트가 바로 열림Application domain 오타
즉시 "Access denied"정책에 본인 이메일 등록 누락
인증 메일 안 옴스팸함 (noreply@notify.cloudflare.com)
무한 리다이렉트쿠키 충돌 → 시크릿 창 사용

아이패드/모바일에서도 동일한 URL로 접속, 같은 이메일 코드 플로우. 사파리에서 인증 후 홈 화면에 추가하면 앱처럼 사용 가능.

7. 일상 워크플로우

내용 업데이트:

bash
# .md 파일 수정 후
npm run deploy

npm run deploy는 자동으로 npm run build를 먼저 실행한다. Access 설정은 그대로 유지되므로 별도 작업 불필요.

관찰 사항

Direct Upload의 장점

  • GitHub 저장소가 필요 없어 Google Drive 같은 클라우드 동기화만으로도 워크플로우 유지 가능
  • 빌드를 로컬에서 하므로 Cloudflare 빌드 환경 의존성 이슈가 없음

Direct Upload의 단점

  • 빌드를 로컬에서 해야 하므로 Node.js 환경이 없는 곳에서는 업데이트 불가
  • 여러 사람이 동시에 작업하기엔 Git 연동 방식이 더 적합

보안 주의

  • 옛 Pages 프로젝트(예: 이름을 바꿔서 새로 만든 경우 옛 이름의 프로젝트)는 반드시 삭제. 안 그러면 Access 미적용 상태로 공개되어 있음
  • Cloudflare Access는 도메인 단위로 적용되므로, 같은 사이트를 여러 도메인에서 서비스하면 모든 도메인에 정책 적용 필요

TODO

  • [ ] 커스텀 도메인 연결 (선택)
  • [ ] 정기 백업 (Cloudflare는 호스팅만 담당, 원본은 로컬/Drive에 있음)

참고

관련 노트

  • 관련 노트 제목

다음 단계: 커스텀 도메인 연결, 빌드 자동화

NDT Research Lab - KRISS