GitHub Pages와 Cloudflare DNS 연결

GitHub Pages에 Cloudflare로 관리하는 커스텀 도메인을 연결할 때 필요한 A 레코드, www CNAME, 프록시 설정, HTTPS와 흔한 오류를 정리했습니다.

GitHub Pages와 Cloudflare를 연결하는 과정은 단순해 보이지만, 설정 순서가 어긋나면 원인을 찾기 어려워집니다. GitHub에는 도메인이 잘못 구성됐다는 경고가 뜨고, www와 루트 도메인 중 한쪽만 열리거나 예전 /repo-name 경로로 이동할 수 있습니다.

먼저 DNS 레코드를 계속 바꾸기보다 GitHub Pages 설정, 루트 도메인, www, 프록시 상태를 순서대로 확인하는 편이 빠릅니다.

먼저 결론부터

example.com 같은 루트 도메인은 저장소의 Pages 설정에 등록한 뒤 GitHub Pages가 안내하는 네 개의 A 레코드로 연결할 수 있습니다.

185.199.108.153
185.199.109.153
185.199.110.153
185.199.111.153

GitHub는 IPv6용 AAAA 레코드도 제공합니다. 다만 IPv6만 쓰지 말고 A 레코드도 함께 유지하도록 권장합니다.

www.example.com에는 GitHub Pages의 기본 도메인을 가리키는 CNAME을 둡니다.

www  CNAME  <username>.github.io

<username>.github.io/my-repo처럼 저장소 경로까지 넣으면 안 됩니다. CNAME 대상은 사용자 또는 조직의 Pages 도메인까지만 적습니다.

설정 순서가 중요하다

안전한 순서는 다음과 같습니다.

  1. GitHub에서 사이트 저장소를 엽니다.
  2. Settings → Pages로 이동합니다.
  3. Custom domain에 최종 도메인을 등록합니다.
  4. 배포 방식에 따라 CNAME 파일이 필요한지 확인합니다.
  5. Cloudflare에 DNS 레코드를 추가합니다.
  6. DNS 전파를 기다립니다.
  7. GitHub에서 사용할 수 있게 되면 Enforce HTTPS를 켭니다.

GitHub 공식 문서는 DNS 제공자에서 레코드를 만들기 전에 Pages 설정에 커스텀 도메인을 추가하도록 안내합니다. GitHub Pages에 도메인을 등록하지 않은 채 DNS만 먼저 연결하면 하위 도메인 탈취 위험이 생길 수 있기 때문입니다.

브랜치에서 배포하면 Pages 설정에 도메인을 저장할 때 CNAME 파일이 만들어질 수 있습니다. 커스텀 GitHub Actions 워크플로로 배포한다면 이 파일이 필수는 아닙니다. 먼저 배포 방식을 확인하고 필요한 경우에만 파일을 둡니다.

Cloudflare DNS 레코드

루트 도메인은 다음처럼 구성할 수 있습니다.

유형 이름 대상 프록시 상태
A @ 185.199.108.153 프록시 또는 DNS 전용
A @ 185.199.109.153 프록시 또는 DNS 전용
A @ 185.199.110.153 프록시 또는 DNS 전용
A @ 185.199.111.153 프록시 또는 DNS 전용

www는 다음과 같습니다.

유형 이름 대상 프록시 상태
CNAME www <username>.github.io 프록시 또는 DNS 전용

Google Search Console이나 Bing의 소유권 확인용 TXT 레코드는 웹 요청을 전달하지 않습니다.

유형 이름 프록시 상태
TXT @ google-site-verification=... DNS 전용
TXT @ msvalidate.01=... DNS 전용

Cloudflare에서는 A, AAAA, CNAME 같은 웹 트래픽용 레코드만 프록시할 수 있습니다. TXT 레코드는 DNS 전용으로 유지됩니다.

Cloudflare 프록시는 켜야 할까

프록시를 켜면 HTTP와 HTTPS 요청이 Cloudflare를 통과합니다. 캐시, WAF 규칙, 리다이렉트와 Cloudflare 분석 기능을 쓸 수 있습니다.

다만 처음부터 반드시 켤 필요는 없습니다.

  1. GitHub Pages가 도메인을 검증하는 중이라면 DNS 전용으로 두는 편이 실제 대상을 확인하기 쉽습니다.
  2. TXT 같은 소유권 확인 레코드는 프록시 대상이 아닙니다.

정적 블로그라면 먼저 DNS 전용 상태에서 GitHub Pages 검증과 HTTPS가 정상인지 확인합니다. Cloudflare 캐시나 WAF가 필요해진 뒤 A와 CNAME 레코드의 프록시를 켜도 늦지 않습니다.

터미널에서 DNS 확인하기

루트 도메인의 A 레코드를 확인합니다.

dig example.com +noall +answer -t A

DNS 전용 상태라면 다음과 같은 결과가 나와야 합니다.

example.com.  300  IN  A  185.199.108.153
example.com.  300  IN  A  185.199.109.153
example.com.  300  IN  A  185.199.110.153
example.com.  300  IN  A  185.199.111.153

www도 확인합니다.

dig www.example.com +noall +answer
www.example.com.  300  IN  CNAME  <username>.github.io.

Cloudflare 프록시가 켜져 있으면 GitHub IP 대신 Cloudflare anycast IP가 보일 수 있습니다. 프록시를 사용한다면 정상적인 결과입니다. 원본 DNS 대상을 확인해야 할 때만 잠시 DNS 전용으로 전환합니다.

흔한 오류

도메인과 대체 도메인이 잘못 구성됐다는 경고

GitHub Pages가 루트 도메인과 www가 올바른 Pages 주소를 가리키는지 확인하지 못할 때 나타날 수 있습니다. 한쪽만 보지 말고 둘을 같이 확인합니다.

[ ] GitHub Pages의 Custom domain이 최종 도메인인가
[ ] 루트 도메인에 네 개의 A 레코드 또는 ALIAS/ANAME이 있는가
[ ] www가 <username>.github.io를 가리키는가
[ ] 오래된 A, AAAA, CNAME 또는 wildcard 레코드가 충돌하지 않는가
[ ] DNS 변경 후 충분히 기다렸는가

GitHub는 DNS 변경 전파에 최대 24시간이 걸릴 수 있다고 안내합니다. 와일드카드 DNS는 하위 도메인 탈취 위험도 있으므로 편의를 위해 추가하지 않는 편이 안전합니다.

Search Console에서 사이트맵을 가져오지 못한다

먼저 파일 자체를 확인합니다.

curl -I https://example.com/sitemap-index.xml
curl -Ls https://example.com/sitemap-index.xml

응답이 200이고 XML 내용이 정상이라면 DNS나 HTTPS를 바꾼 직후 Search Console에 일시적인 오류가 남아 있을 수 있습니다. 사이트맵 인덱스가 계속 실패할 때만 하위 사이트맵도 확인합니다.

https://example.com/sitemap-0.xml

/repo-name으로 리다이렉트된다

정적 사이트가 예전 GitHub Pages 프로젝트 경로를 base로 둔 채 빌드됐을 가능성이 큽니다. Astro에서 커스텀 도메인을 쓴다면 운영 설정의 site는 최종 도메인이고, 저장소 이름을 위한 base는 남아 있지 않아야 합니다.

export default defineConfig({
  site: "https://example.com",
});

https://username.github.io/repo-name으로 배포할 때는 base가 필요할 수 있습니다. https://example.com을 쓰는 시점에는 보통 제거하는 것이 맞습니다.

운영 기준

GitHub Pages와 Cloudflare를 함께 쓰는 정적 블로그라면 다음 구성이 단순합니다.

이 구조는 글 URL을 커스텀 도메인 아래에 고정합니다. 나중에 호스팅을 옮겨도 글 주소를 유지하기 쉽고, 검색 데이터도 하나의 도메인에 쌓입니다.

참고 자료

이어서 읽기

호스팅 선택 기준은 Vercel vs Cloudflare Pages vs GitHub Pages 비교에서, 정적 호스팅의 검색 노출 기준은 GitHub Pages 블로그 SEO에서 이어서 볼 수 있습니다.