GitHub Pages 커스텀 도메인 연결 4단계 — Cloudflare DNS·CNAME·HTTPS 자동·검색엔진 재등록
이 글은 제가 taystudio.github.io 를 taystudios.com 으로 옮긴 작업을 정리한 후기입니다. 실제 작업은 2026-05-09 에 했고, 6/5 시점에 30일치 데이터가 다 나와서 어떻게 됐는지 실측까지 함께 적어둡니다.
왜 옮겼나
솔직히 .github.io 도 잘 굴러갑니다. 한국 SEO 만 놓고 보면 차이도 거의 없고요. 그런데도 옮긴 건 네 가지가 계속 마음에 걸렸기 때문입니다.
- 도메인 권위가 0부터 시작합니다.
.github.io가 Public Suffix List 에 등재돼 있어서 브라우저와 검색엔진이 이걸 서브도메인으로 취급합니다. 덕분에taystudio.github.io와someone.github.io가 서로 영향을 안 주게끔 격리되는데, 안전한 건 좋지만 그만큼 권위가 누적되지 않습니다. - 영어권 AdSense RPM 이 아쉽습니다. 영어 시장에서
.github.ioURL 은 아무래도 개발자 블로그라는 인상을 주다 보니 일반 독자의 CTR 이 낮습니다. RPM 이 보통$1~3정도에 머무는데,.com으로 가면$3~8까지 봤다는 사례가 많더군요. - 언론·매체 백링크 측면에서도 불리합니다. 기자나 신뢰도 있는 블로그는
.github.ioURL 인용 자체를 꺼리는 경향이 있습니다. 진지한 출처로는 잘 안 보이는 거죠. - 마지막으로 브랜드 문제입니다. URL 에 "github" 가 박혀 있는 것만으로도 brand 가 약해 보입니다.
영어 시장과 AdSense, 그리고 brand. 이 셋이 저한테는 모두 결정적이어서 결국 옮기기로 했습니다. 다만 한 가지 강조하고 싶은 건 타이밍입니다. URL 이 수백 개 쌓이고 백링크가 박히기 시작하면 옮기는 비용이 폭증하거든요. 제 사이트는 그때 100개 정도였는데, 경험상 그 정도가 옮기기에 딱 좋은 시점이었습니다.
4단계 요약
① Cloudflare DNS 설정 (A 4개 + CNAME www)
② GitHub repo CNAME 파일 (1줄)
③ 사이트 일괄 치환 (canonical·sitemap·robots)
④ 검색엔진 재등록 (GSC·Naver·Bing·Daum)
전체 과정에서 다운타임은 0초였습니다. 양쪽 도메인이 다 살아있는 상태로 점진적으로 전환됩니다.
1. Cloudflare DNS 설정
저는 도메인을 Cloudflare Registrar 에서 샀습니다. 물론 가비아든 후이즈든 어디서 사도 상관없습니다. DNS 도 그대로 Cloudflare 를 쓰는데, 경험상 전파가 가장 빠르고 무료라 따로 옮길 이유가 없었습니다.
UI — 어디서 뭘 누르나
- dash.cloudflare.com 에 로그인한 뒤 사이트를 클릭하고, 좌측 메뉴에서 DNS → Records 로 들어갑니다.
Add record버튼을 눌러 아래 5개를 입력합니다.
| Type | Name | Content (Value) | Proxy status |
|---|---|---|---|
| A | @ |
185.199.108.153 |
DNS only (회색 구름) |
| A | @ |
185.199.109.153 |
DNS only |
| A | @ |
185.199.110.153 |
DNS only |
| A | @ |
185.199.111.153 |
DNS only |
| CNAME | www |
<본인 username>.github.io |
DNS only |
Name 칸에 @ 를 치면 자동으로 apex (taystudios.com) 로 변환됩니다. www 는 그냥 www 만 입력하면 www.taystudios.com 으로 잡힙니다.
함정 두 개
여기서 제가 걸렸던, 혹은 자칫 걸리기 쉬운 함정이 두 가지 있습니다.
- A record 는 4개를 다 등록해야 합니다. GitHub Pages 가 이 4개 IP 로 load balancing 을 하기 때문에, 하나만 박아두면 그 IP 가 다운될 때 사이트가 같이 죽습니다.
- Proxy 는 처음엔 반드시 DNS only (회색 구름) 로 둬야 합니다. 주황 구름(Proxy ON)으로 켜버리면 GitHub Pages 의 Let's Encrypt 인증서가 origin IP 를 못 잡아서 cert 발급이 실패합니다. Proxy 는 인증서 발급이 다 끝난 다음에 켜는 게 안전합니다.
확인
dig taystudios.com +short
# 185.199.108.153
# 185.199.109.153
# 185.199.110.153
# 185.199.111.153
dig www.taystudios.com +short
# taystudio.github.io.
# 185.199.108.153
# ...
전 세계 resolver 캐시까지 전파되는 데는 보통 30분에서 24시간 정도 걸립니다. 저의 경우 한국에서는 1시간 안에 됐습니다.
2. GitHub repo 의 CNAME 파일
이 파일은 GitHub Pages 에 "이 repo 가 어떤 도메인을 받을지" 를 알려주는 핵심 파일입니다.
파일 만들기
repo 루트에 파일명을 정확히 CNAME 으로 만듭니다. 확장자는 없고, 전부 대문자입니다. 그 안에 한 줄만 적으면 됩니다.
taystudios.com
www 가 없는 apex 도메인입니다. 이게 전부입니다.
GitHub UI 에서 설정
- repo 페이지로 가서 상단 Settings 탭을 엽니다.
- 좌측 메뉴에서 Pages 를 선택합니다.
- Custom domain 입력란에
taystudios.com을 치고 Save 를 누릅니다. - 잠시(5~30분) 기다리면
✓ DNS check successful메시지가 뜹니다. - 그 아래 Enforce HTTPS 체크박스가 활성화되면 체크해 줍니다.
Custom domain 에 입력하면 GitHub 가 알아서 repo 루트에 CNAME 파일을 만들어 줍니다. 위 1번처럼 직접 만들어도 결과는 똑같습니다.
Let's Encrypt 인증서
GitHub 가 Let's Encrypt 에서 SSL 인증서를 자동으로 발급해 줍니다. 보통 5분에서 30분 정도 걸리고, 발급이 끝나면 회색이던 Enforce HTTPS 체크박스가 클릭 가능한 상태로 바뀝니다.
90일마다 자동 갱신되고, 비용은 0원이며, 따로 설정할 것도 없습니다.
→ 인증서 발급이 끝난 다음에 Cloudflare 로 돌아가서 Proxy 를 켜도 됩니다 (선택 사항입니다).
3. 사이트 일괄 치환
migration 에서 SEO 적으로 제일 중요한 부분입니다. 옛 도메인을 가리키는 URL 이 어디 하나라도 남아 있으면 Google 이 옛 도메인을 canonical 로 인식해버려서, 권위 이전이 되지 않습니다.
바꿔야 할 곳
| 영역 | 변경 |
|---|---|
<link rel="canonical"> |
taystudios.com/... |
<meta property="og:url"> |
동일 |
<link rel="alternate" hreflang> |
동일 |
sitemap.xml 의 <loc> |
동일 |
robots.txt 의 Sitemap: URL |
동일 |
llms.txt (있다면) |
동일 |
schema.org JSON-LD 의 @id·url |
동일 |
| 내부 절대 경로 link | taystudio.github.io → taystudios.com |
| IndexNow key file URL | 동일 |
우리 처리
저는 build script (blog/scripts/build.py) 가 site.json 의 siteUrl 하나만 보고 전부 자동으로 갱신하게 짜둬서, 그 값 한 줄을 바꾸고 빌드를 한 번 돌리니 끝났습니다.
build script 를 안 쓰는 경우라면 sed 로 처리하면 됩니다.
# 옛 도메인 → 새 도메인 일괄 치환
grep -rl "taystudio.github.io" . | xargs sed -i '' 's|taystudio.github.io|taystudios.com|g'
(macOS sed 는 -i '', Linux 는 -i 입니다.)
치환을 마친 뒤 GitHub 에 push 하면 자동으로 deploy 됩니다.
4. 검색엔진 재등록
.com 은 Google·Naver·Bing·Daum 입장에서 보면 완전히 신규 도메인입니다. 옛 property 에 쌓인 데이터가 자동으로 이전되지 않으니 새로 등록해야 합니다.
Google Search Console
- search.google.com/search-console 에 들어가 좌상단 속성 추가 를 누릅니다.
- URL 접두어 를 선택하고
https://taystudios.com을 입력합니다. - 소유권을 확인합니다. 여러 방법 중 HTML 태그 방법이 제일 쉽습니다.
<meta name="google-site-verification" content="...">한 줄을 받아서<head>에 박고 빌드한 뒤 확인을 누르면 됩니다. - 좌측 Sitemaps 에서
sitemap.xml을 입력하고 제출합니다. - URL 검사 에서 우선순위가 높은 페이지(홈·인기 글)의 URL 을 넣고 색인 생성 요청 을 합니다. 하루 10개 한도입니다.
→ Bing Webmaster 는 GSC sitemap 을 자동 import 하는 기능이 있어서, GSC 만 해두면 Bing 도 같이 잡힙니다.
Naver SearchAdvisor
- searchadvisor.naver.com 에 로그인한 뒤 우상단 사이트 관리 로 들어갑니다.
- 사이트 등록 에
https://taystudios.com을 입력합니다. - 소유권 확인은 HTML 파일을 다운로드받아 사이트 루트에 업로드하고, 빌드한 뒤 확인하면 됩니다.
- 좌측 요청 → 사이트맵 제출 에서
sitemap.xml을 넣습니다. - 요청 → 웹페이지 수집 에서 개별 URL 을 한 줄씩 넣습니다 (하루 50건).
→ 한국 트래픽은 Naver 가 80% 정도를 받쳐주기 때문에, 저로서는 GSC 보다 Naver 가 더 급했습니다.
Bing Webmaster
- bing.com/webmasters 에 Microsoft 계정으로 로그인합니다.
- 사이트 추가 에서 GSC 로부터 자동 import 하는 방식을 권장합니다.
- 옛 도메인 property 가 있다면 사이트 이동(Site Move) 기능을 쓸 수 있습니다. 명시적인 이동 신호를 전달해 줍니다.
Daum 웹마스터 도구
(이름이 SearchAdvisor 가 아닙니다. UI 상 메뉴는 여전히 "웹마스터 도구" 이고, URL 은 webmaster.daum.net 입니다.)
- webmaster.daum.net 에 카카오 계정으로 로그인합니다.
- 사이트 등록 에
https://taystudios.com을 입력합니다. - 소유권은 meta 태그를 쓰거나, 인증 토큰을
robots.txt첫 줄에 추가해서 확인합니다. - 사이트맵 메뉴에서
sitemap.xml을 제출합니다. - 수집 요청 에서 개별 URL 을 넣습니다.
IndexNow (덤)
Bing·Yandex·Naver·Seznam 에 동시에 ping 을 보내는 방식입니다. key 를 한 번만 발급받아서 robots.txt 에 박아두면 됩니다.
curl "https://api.indexnow.org/IndexNow?url=https://taystudios.com/&key=<your-key>"
DNS·CNAME 이 뭔지
migration 을 하다 보면 이게 다 무슨 소린가 싶어질 때가 있어서, 한 번 정리해 둡니다. 알고 나면 위의 4단계가 왜 그런 모양으로 생겼는지가 보입니다.
DNS = 전화번호부
사람은 이름(taystudios.com)을 기억하지만, 컴퓨터는 IP(185.199.108.153)만 인식합니다. 이 이름과 IP 사이를 통역해 주는 게 DNS 입니다.
브라우저가 IP 찾는 5단계
(resolver 캐시가 다 비었을 때 기준입니다.)
브라우저
→ ISP DNS (KT·SKB 8.8.8.8 등)
→ Root nameserver (".")
→ TLD nameserver (".com")
→ 도메인 nameserver (Cloudflare)
→ A record 응답 (185.199.108.153)
물론 실제로는 resolver 가 TTL(기본 1시간) 동안 결과를 캐시하기 때문에 매번 root 까지 올라가진 않습니다. 다만 도메인을 처음 사거나 DNS record 를 바꾸면 전 세계 resolver 캐시가 비어 있어서 이 5단계를 다 거쳐야 하는데, 이게 바로 DNS 전파(propagation) 입니다.
A vs CNAME
A record 는 도메인을 IP 로 직접 연결합니다.
taystudios.com A 185.199.108.153
CNAME 은 도메인을 다른 도메인(alias)으로 연결합니다.
www.taystudios.com CNAME taystudio.github.io
resolver 가 CNAME 을 받으면 "그 다른 도메인의 A 를 다시 조회" 합니다. 한 단계를 더 거치는 셈이지만, 앞 도메인의 IP 가 바뀌어도 자동으로 따라가 준다는 장점이 있습니다.
apex (zone root) 엔 CNAME 못 씀 — RFC 1912
taystudios.com 자체에는 CNAME 을 쓸 수 없습니다. 다른 record(MX·NS)와 충돌이 나기 때문에 표준상 금지돼 있습니다.
반면 www.taystudios.com·blog.taystudios.com 같은 건 CNAME 이 가능합니다.
→ 그래서 apex 는 A 4개로, www 는 CNAME 으로 잡는 겁니다. Cloudflare 는 "CNAME flattening" 으로 apex CNAME 을 흉내 낼 수 있긴 하지만, GitHub Pages 의 공식 권장은 A 4개입니다.
Host header
GitHub Pages 의 IP 4개(185.199.108~111.153)는 수백만 개의 사이트가 공유합니다. 그런데 어떻게 그 중 내 사이트만 정확히 찾아오는 걸까요?
HTTP/1.1 GET /
Host: taystudios.com ← 이게 핵심
브라우저가 보내는 Host 헤더와, GitHub 내부에서 CNAME 파일 == "taystudios.com" 인 repo 를 찾아 매핑하는 과정이 맞물려서 돌아갑니다. 결국 repo 의 CNAME 파일 한 줄이 결정적인 역할 을 하는 셈입니다.
우리 실측 — sandbox 30일
5/9 migration 직후 30일 동안의 데이터입니다.
| 시점 | GSC 노출 | Naver 노출 |
|---|---|---|
| 5/9 (migration) | 0 | (옛 도메인 잔여) |
| 5/14 (Week 1) | 450 peak | spike 시작 |
| 5/24 (Week 3) | 10 (dip) | 7,600 peak |
| 6/2 (Week 4) | ~0 | 2,000-3,000/일 안정 |
Google 은 sandbox 에 진입한 게 명확히 보입니다. 6-12주 정도를 예상하면 됩니다. 반면 Naver 는 sandbox 가 없어서 바로 회복했습니다. 이 부분에 대한 자세한 회고는 Google sandbox 한 달 실측 글에 따로 정리해 뒀습니다.
같은 작업 할 사람한테
같은 작업을 앞두고 있는 분이라면, 제가 겪어보고 정리한 네 가지만 기억하시면 좋겠습니다.
- URL 적을 때 옮기세요. 백링크가 박히기 전이 제일 쌉니다. 100개 넘게 쌓이고 나면 redirect·canonical 작업 비용이 폭증합니다.
- 다운타임은 0 입니다. 양쪽 도메인이 동시에 작동하기 때문에, 사용자가 옛 도메인으로 들어와도 GitHub 가 새 도메인으로 자동 redirect 해 줍니다 (단, 옛 repo 의 CNAME 파일은 비워둬야 합니다).
- canonical 일관성 이 중요합니다. sed 든 build script 든 한 번에 일괄 치환하세요. 하나라도 옛 도메인이 남으면 권위 이전이 실패합니다.
- Google 만 보고 패닉하지 마세요. sandbox 라서 한 달 정도는 노출이 거의 0 이 됩니다. Naver·Bing·Cloudflare 까지 합쳐서 봐야 사이트가 정상적으로 돌아가고 있다는 게 보입니다.
도메인을 옮기는 작업 자체는 1시간이면 끝납니다. 다만 권위가 이전되는 데는 1-3개월을 기다려야 한다는 점만 감안하시면 됩니다.
관련 글
- Google sandbox 한 달 실측 — migration 후 30일 GSC·Naver·Cloudflare 추적
- Naver SearchAdvisor 등록 가이드 — 한국 트래픽 80% 채널
- GSC vs Naver vs Cloudflare — 3종 데이터 비교
댓글