13. Cloudflare — DNS부터 배포와 비공개 접근까지
이 장에서 처음 나오는 말5개
reverse proxyReverse Proxy- 사용자와 origin 사이에서 요청을 먼저 받고, 직접 응답하거나 뒤의 서버로 전달하는 중계층이다.
edgeNetwork Edge- 사용자 가까이에서 요청을 처리하는 Cloudflare의 네트워크 지점이다. cache뿐 아니라 보안 검사와 코드 실행도 맡는다.
bindingWorkers Binding- Worker가 별도 secret 없이 KV·R2·D1 같은 Cloudflare 자원에 접근하도록 권한과 API를 함께 연결하는 방식이다.
AccessCloudflare Access- 요청자의 identity와 정책을 확인해 애플리케이션에 들어갈 사람을 결정하는 identity-aware proxy다.
TunnelCloudflare Tunnel- origin의
cloudflared가 Cloudflare로 outbound 연결을 만들어 공개 IP 없이도 요청이 origin에 도달하게 하는 통로다.
Cloudflare를 제품 이름으로 외우면 DNS·Pages·Workers·Access가 서로 무슨 관계인지 흐려진다. 이 장은 1장의 요청 경로에 Cloudflare를 꽂아 두 질문에 답한다.
- 요청은 어느 지점에서 끝나고, 언제 기존 origin까지 가는가?
- 성능·보안·실행·비공개 접근 중 어떤 문제에 어떤 제품을 붙이는가?
큰 그림 — 앱을 운영하거나 앱 앞에 선다
섹션 제목: “큰 그림 — 앱을 운영하거나 앱 앞에 선다”Cloudflare는 애플리케이션을 직접 운영할 수도 있고, 이미 다른 곳에 있는 애플리케이션의 앞단이 될 수도 있다. Pages·Workers는 전자이고, proxied DNS·CDN·WAF·Tunnel은 후자다.
그림은 제품의 개념적 위치를 보여 주며 내부 실행 phase의 정확한 순서를 뜻하지 않는다. 핵심은 요청이 edge에서 끝날 수도 있고, Cloudflare에서 코드를 실행할 수도 있고, 기존 origin으로 계속 갈 수도 있다는 점이다.
주요 제품은 다음 층에 꽂아 두면 된다.
| 층 | 푸는 문제 | 대표 제품 |
|---|---|---|
| 네트워크 앞단 | 이름 해석, 요청 경로, cache와 가속 | DNS, CDN, Load Balancing, Argo Smart Routing |
| 애플리케이션 보안 | 공격·봇·과도한 요청을 origin 전에 처리 | DDoS Protection, WAF, Bot Management, Turnstile |
| 실행 | 정적 자산과 요청 코드를 배포 | Pages, Workers, Queues, Workflows |
| 데이터 | 파일·SQL·key-value·공유 상태를 저장 | R2, D1, KV, Durable Objects |
| 비공개 연결 | origin을 노출하지 않고 연결하고 사용자를 확인 | Tunnel, Access, Cloudflare One Client |
| 미디어와 AI | 이미지·영상·모델·vector workload를 제공 | Images, Stream, Workers AI, Vectorize |
이 장은 일반 웹 개발자가 요청 경로에서 자주 만나는 앞의 다섯 층까지만 다룬다.
DNS와 proxy — 주황 구름이 경로를 바꾼다
섹션 제목: “DNS와 proxy — 주황 구름이 경로를 바꾼다”Cloudflare를 authoritative DNS로 쓴다는 사실만으로 모든 HTTP 요청이 Cloudflare를 통과하지는 않는다. DNS 레코드의 proxy 상태가 경로를 결정한다.
| 레코드 상태 | DNS가 돌려주는 주소 | HTTP 요청 경로 | 적용되는 것 |
|---|---|---|---|
| DNS only, 회색 구름 | 설정한 origin 주소 | 브라우저 → origin | DNS 응답만 Cloudflare가 담당 |
| Proxied, 주황 구름 | Cloudflare Anycast IP | 브라우저 → Cloudflare → origin | CDN·TLS·WAF·규칙 등 edge 기능 |
Cloudflare의 공식 요청 경로 설명처럼 proxied 레코드는 origin IP 대신 Cloudflare Anycast IP를 응답한다. 사용자의 HTTP·HTTPS 요청은 Cloudflare의 reverse proxy에 먼저 도착하고, 여기서 직접 처리하거나 origin으로 전달된다.
reverse proxy가 앞에 서면 한 지점에서 여러 일을 할 수 있다.
- TLS 연결을 받아 HTTPS를 제공한다
- cache 가능한 응답을 가까운 edge에서 돌려준다
- 악성 요청을 origin에 도달하기 전에 거른다
- rewrite·redirect·header 같은 규칙을 적용한다
- cache MISS와 동적 요청만 origin으로 전달한다
보안 — 트래픽, 요청, 사람을 구분한다
섹션 제목: “보안 — 트래픽, 요청, 사람을 구분한다”Cloudflare의 보안 제품은 모두 “막는다”로 보이지만 판단 대상이 다르다.
| 기능 | 판단하는 것 | 대표적인 사용 |
|---|---|---|
| DDoS Protection | 비정상적인 트래픽 양과 공격 pattern | 대량의 network·HTTP 공격을 edge에서 자동 완화 |
| WAF | URL·header·body 같은 개별 HTTP 요청 | 알려진 공격 pattern, custom rule, rate limit |
| Turnstile | 폼을 제출하는 browser가 사람인지 봇인지 | 가입·로그인·문의 폼의 bot 방어 |
| Access | 로그인한 identity가 이 앱에 들어와도 되는지 | 사내 도구·개인 문서·관리 화면 보호 |
DDoS Protection은 분산 서비스 거부 공격을 자동으로 탐지·완화하고, WAF는 ruleset으로 웹·API 요청을 검사한다. 둘은 공격을 다루지만 “누구에게 이 문서를 보여 줄 것인가”를 결정하는 로그인 장치는 아니다.
Turnstile은 CAPTCHA 대안이다. browser widget이 token을 만들고 서버가 Siteverify API로 검증해야 방어가 완성된다. CDN을 쓰지 않는 사이트에도 붙일 수 있다는 점에서 proxied DNS와 독립적이다.
Pages와 Workers — 파일을 둘까, 요청을 실행할까
섹션 제목: “Pages와 Workers — 파일을 둘까, 요청을 실행할까”Pages와 Workers는 둘 다 Cloudflare 네트워크에 애플리케이션을 배포하지만 출발점이 다르다.
| 선택 | 출발점 | 잘 맞는 경우 | 서버 동작 |
|---|---|---|---|
| Pages | Git 저장소와 front-end build output | 문서·블로그·SPA, PR preview가 중요한 front-end | 필요하면 Pages Functions 추가 |
| Workers + Static Assets | Worker code와 정적 자산을 한 배포 단위로 구성 | API·routing·binding 중심 full-stack 앱 | Worker가 요청을 직접 처리 |
| 기존 origin + Cloudflare 앞단 | 이미 운영 중인 VM·container·PaaS | runtime을 옮기지 않고 CDN·WAF만 추가 | 기존 서버가 계속 실행 |
Pages는 GitHub·GitLab과 연결해 branch별 preview와 production 배포를 만드는 흐름이 자연스럽다. Workers도 Static Assets를 함께 배포할 수 있으므로 “정적이면 무조건 Pages, 동적이면 무조건 Workers”라는 절대 경계는 아니다. 배포 workflow가 Git 중심인지, 요청 code와 binding 중심인지로 먼저 고른다.
이 스터디 사이트는 Astro가 dist/를 만들고 Cloudflare Pages가 그 파일을 배포한다. 서버에서 매 요청마다
HTML을 만들 필요가 없으므로 Pages가 맞고, 검색 index도 build 시점에 함께 생성된다.
데이터와 상태 — 모양이 아니라 읽기·쓰기 성질로 고른다
섹션 제목: “데이터와 상태 — 모양이 아니라 읽기·쓰기 성질로 고른다”Worker는 기본적으로 stateless다. 요청 사이에 남겨야 할 데이터는 성질에 맞는 저장소로 보낸다.
| 제품 | 데이터 모양 | 강점 | 먼저 의심할 함정 |
|---|---|---|---|
| KV | key-value | read-heavy 설정·cache를 전 세계에서 낮은 지연으로 읽기 | eventual consistency라 같은 key의 잦은 쓰기에는 부적합 |
| R2 | object·file | 이미지·backup·사용자 업로드 같은 비정형 데이터 | object storage이지 관계형 DB가 아님 |
| D1 | SQLite SQL | schema·join·transaction이 필요한 serverless 관계형 데이터 | workload와 제한을 확인하고 기존 대형 DB를 무조건 대체하지 않기 |
| Durable Objects | identity별 compute + storage | chat room·game session처럼 한 공유 상태를 순서대로 조정 | 모든 데이터를 객체 하나에 몰지 말고 coordination 단위로 나누기 |
이 자원들은 보통 binding으로 Worker에 연결한다. binding은 “이 Worker가 이 bucket이나 DB를 쓸 수 있다”는 capability와 API를 함께 주므로, 같은 계정의 자원을 호출하려고 application code에 API key를 박지 않아도 된다.
오래 걸리는 여러 단계를 재시도하며 이어 가야 하면 Workflows, 비동기 생산자와 소비자를 분리하려면 Queues를 검토한다. 저장소 하나로 실행 흐름까지 억지로 표현하지 않는다.
Access와 Tunnel — 문지기와 통로를 나눈다
섹션 제목: “Access와 Tunnel — 문지기와 통로를 나눈다”둘은 함께 자주 쓰이지만 역할이 다르다.
| Access | Tunnel | |
|---|---|---|
| 질문 | 이 요청자가 들어와도 되는가? | Cloudflare가 origin까지 어떻게 도달하는가? |
| 기준 | email·IdP group·device posture 같은 policy | hostname을 내부 service 주소에 mapping |
| 결과 | 허용 사용자에게 application token 발급 | cloudflared의 outbound 연결로 요청 전달 |
| 단독 사용 | Pages·공개 hostname 앞에도 사용 가능 | 인증 없이 쓰면 공개 application이 될 수 있음 |
공개 hostname Access application은 browser에서 로그인하게 하므로 사용자의 device에 client를 설치할 필요가 없다. Access policy는 default-deny라 Allow policy와 일치한 identity만 통과한다.
Tunnel은 내부의
cloudflared가 Cloudflare로 outbound 연결을 만든다. inbound port나 공개 origin IP를 열지 않고도 기존
서버에 요청을 전달할 수 있지만, Tunnel 자체가 사용자 인증을 뜻하지는 않는다. 공개하면 누구나 도달할 수
있으므로 비공개 앱이라면 Access policy를 별도로 붙인다.
이 사이트 — Pages를 본인만 보게 만들기
섹션 제목: “이 사이트 — Pages를 본인만 보게 만들기”현재 배포는 GitHub의 main이 Pages production을 만들고, 같은 배포가 커스텀 도메인과
study-starlight.pages.dev에서 제공되는 구조다. 다른 branch에는 별도의 preview URL도 생긴다.
커스텀 도메인 하나에만 Access를 붙이면 끝나지 않는다. Pages는 production 기본 주소와 과거 commit을 가리키는 preview 주소도 만들기 때문에 모든 진입점을 함께 닫아야 한다.
-
커스텀 도메인을 Access application으로 보호한다
study.upggu.com전체를 public hostname application으로 등록하고, Allow policy의Emails에 본인의 정확한 email만 넣는다. Cloudflare identity provider로 로그인하거나, One-time PIN IdP를 추가해 email OTP를 받을 수 있다. -
Pages preview deployment의 Access policy를 켠다
Pages project의 Settings → General → Enable access policy를 켠다. 이 설정은
<hash>.study-starlight.pages.dev같은 preview를 보호하지만, 공식 문서의 주의처럼 production*.pages.dev와 커스텀 도메인은 보호하지 않는다. -
production
pages.dev를 보호된 도메인으로 보낸다account-level Bulk Redirect로
study-starlight.pages.dev를https://study.upggu.com으로 보낸다. Pages의 권장 구성은 preview Access와 production 기본 주소 redirect를 함께 사용한다. -
원본 문서가 비밀이면 Git 저장소도 private으로 바꾼다
Access는 배포된 사이트만 보호한다. public GitHub repository의 MDX는 계속 누구나 읽을 수 있다. Cloudflare Pages의 Git integration은 private repository도 지원하므로 Cloudflare GitHub App이 해당 저장소를 계속 읽을 권한만 확인한다.
-
허용·차단·우회 경로를 각각 검증한다
로그인한 browser에서 본문이 보이는지, 시크릿 창에서는 Access login으로 가는지 확인한다. production
pages.dev는 보호된 커스텀 도메인으로 redirect되는지, preview URL은 인증을 요구하는지도 별도로 확인한다.
무엇부터 쓸까 — 요구에서 제품으로
섹션 제목: “무엇부터 쓸까 — 요구에서 제품으로”| 지금 필요한 것 | 먼저 볼 제품 | 이유 |
|---|---|---|
| Git push로 정적 문서·SPA 배포와 PR preview | Pages | build output과 branch deployment가 중심 |
| API·routing·Cloudflare 자원을 쓰는 full-stack 앱 | Workers + Static Assets | 요청 code와 binding이 중심 |
| 기존 서버는 유지하고 속도·TLS·보안만 개선 | Proxied DNS + CDN/WAF | runtime migration 없이 앞단만 추가 |
| 내부 서버를 공개 IP 없이 Cloudflare에 연결 | Tunnel | origin에서 시작하는 outbound 연결 |
| 특정 사용자만 웹 앱에 접근 | Access | identity 기반 application policy |
| 이미지·첨부 파일 | R2 | object storage |
| 관계형 app 데이터 | D1 또는 기존 외부 DB | SQL·transaction이 중심 |
| chat room처럼 공유 상태를 순서대로 조정 | Durable Objects | identity별 stateful coordination |
| 전 세계에서 자주 읽는 설정·cache | KV | read-heavy key-value access |
Cloudflare 제품을 많이 쓰는 것이 목표가 아니다. 요청이 어디까지 가야 하는지, 상태의 일관성이 얼마나 강해야 하는지, 기존 origin을 유지할지를 먼저 정하고 필요한 층만 선택한다.
13장 요약
섹션 제목: “13장 요약”- proxied DNS는 이름만 관리하는 것이 아니라 HTTP 요청을 Cloudflare reverse proxy로 보낸다
- edge에서는 CDN·TLS·DDoS·WAF를 적용하고, Pages 자산을 내거나 Workers code를 실행할 수 있다
- Pages는 Git과 front-end build 중심, Workers는 요청 code와 binding 중심으로 먼저 구분한다
- KV·R2·D1·Durable Objects는 데이터 모양보다 읽기·쓰기·일관성·coordination 요구로 고른다
- Access는 누가 들어오는지, Tunnel은 Cloudflare가 origin에 어떻게 도달하는지를 맡는다
- Pages를 비공개로 만들 때는 커스텀 도메인·production
pages.dev·preview·source repository를 모두 확인한다