이 글에서는 '왜 도메인 루트에는 CNAME을 설정할 수 없는가?'라는 질문을 출발점 삼아, DNS와 dig, A 레코드, CNAME 레코드, ALIAS/ANAME 레코드를 입문자 눈높이에서 차근차근 살펴보겠습니다.
먼저 알아야 할 기본 개념
- 도메인 네임 시스템(DNS): 사람이 기억하기 쉬운 도메인 이름(example.com)을 IP 주소(93.184.216.34)로 변환하는 전체 시스템입니다. 해당 IP 주소는 웹페이지 표시에 필요한 파일이 저장된 서버, 즉 보통 웹 서버를 가리킵니다.
- DNS 서버(네임서버라고도 함): DNS 소프트웨어를 사용해 도메인 주소 정보를 저장하는 서버입니다. 여러 계층으로 나뉘는데, 각 ISP가 운영하는 서버, 루트 서버(전 세계 13대), 최상위 도메인(TLD, 예: '.com') 서버, 도메인 단위 DNS 서버 등이 있습니다.
- 도메인 이름: 도메인(example)과 TLD(.com)를 합친 것입니다. 흔히 '도메인'이라는 용어를 도메인 이름과 같은 의미로 쓰지만, 엄밀히는 다릅니다. 등록기관(registrar)이나 리셀러로부터 '도메인'을 구매한다는 것은 특정 도메인 이름(example.com)과 그 하위에 생성하고 싶은 모든 서브도메인(my-site.example.com, mail.example.com 등)에 대한 권리를 구입하는 것입니다.
DNS 조회의 큰 흐름
브라우저에 "example.com"을 입력했을 때 일어나는 과정을, ISP·루트·TLD DNS 서버를 거치는 단계를 생략한 단순화된 흐름으로 표현하면 다음과 같습니다.

하나의 도메인은 보통 두 개 이상의 네임서버를 가지며, 네임서버에는 해당 도메인 이름(example.com)과 관련된 레코드들이 담겨 있습니다.
저장할 수 있는 레코드 유형은 다양하고, 대부분 유형당 여러 개의 항목을 가질 수 있습니다:
A: 도메인 이름을 IP 주소로 매핑하는 주소(Address) 레코드CNAME: 정식 이름(Canonical Name) 레코드. 한 도메인 이름(또는 서브도메인)을 다른 이름의 별칭으로 지정할 때 사용합니다. 뒤에서 자세히 다룹니다.MX: 메일 교환(Mail eXchange) 레코드. 메일 배달 에이전트에게 이메일을 어디로 전달해야 하는지 알려줍니다.TXT: 다양한 용도로 문자열을 저장하는 유연한 텍스트(Text) 레코드SOA: 도메인 최상위에 하나만 존재하는 권한 시작(Start of Authority) 레코드. 기본 네임서버 등 도메인에 대한 필수 정보를 담고 있습니다.NS: 해당 도메인과 연결된 네임서버 정보
기기가 보낸 질의(query)가 네임서버에 도착하면, 서버는 도메인의 레코드 노드에서 A 레코드와 거기에 저장된 IP 주소(example.com → 93.184.216.34)를 찾습니다. 그 결과가 기기로 반환되고, 기기는 이 IP 주소를 사용해 올바른 웹 서버에 요청을 보내 원하는 웹페이지나 리소스를 받아옵니다.
'dig' 명령어 활용하기
dig(domain information groper)는 DNS 서버에 질의를 보낼 수 있는 커맨드라인 도구입니다. 주로 문제 해결(troubleshooting)에 쓰이며, 지금처럼 시스템 구성을 이해할 때도 유용합니다.
$ dig example.com을 실행하면 터미널에 긴 응답이 출력되는데, 우리가 주목할 부분은 ANSWER SECTION(응답 섹션)입니다.
;; ANSWER SECTION:
example.com. 72703 IN A 93.184.216.34이렇게 example.com이 A 레코드로 93.184.216.34를 반환한다는 것을 확인할 수 있습니다. 여러 웹 서버가 동일한 정보를 제공할 수 있는 경우, 하나의 도메인이 여러 개의 A 레코드를 갖기도 합니다.
여기서 끝이 아닙니다! 다른 예제를 몇 가지 시도해 보면 또 다른 흔한 레코드인 CNAME을 만나게 됩니다.
$ dig www.skyscanner.net 실행 결과:
;; ANSWER SECTION:
www.skyscanner.net. 169 IN CNAME www.skyscanner.net.edgekey.net.
www.skyscanner.net.edgekey.net. 5639 IN CNAME e11316.a.akamaiedge.net.
e11316.a.akamaiedge.net. 20 IN A 23.217.6.192+short 플래그를 붙이면 별칭 체인의 경로를 한눈에 확인할 수 있습니다:
$ dig www.skyscanner.net +short
www.skyscanner.net.edgekey.net.
e11316.a.akamaiedge.net.
23.217.6.192CNAME이란?
CNAME 레코드는 한 도메인 이름을 다른 정식(canonical) 도메인의 별칭으로 사용할 수 있게 해줍니다.
DNS 서버가 CNAME 레코드를 발견하면 클라이언트에게 그 값을 바로 반환하지 않습니다. 대신 반환된 도메인 이름을 다시 조회하여 최종적으로 A 레코드의 IP 주소를 돌려줍니다. 이 체인은 여러 단계의 CNAME으로 이어질 수 있으며, 캐싱이 되기 전까지는 조회가 반복되면서 약간의 성능 저하가 발생할 수 있습니다.
간단한 예를 들어볼까요? 모든 사진을 보관하는 서버가 있고, 평소에는 photos.example.com으로 접속한다고 합시다. 그런데 photographs.example.com으로도 접근할 수 있게 하고 싶다면 어떻게 할까요? 한 가지 방법은 photographs가 photos를 가리키는 CNAME 레코드를 추가하는 것입니다. 이렇게 하면 photographs.example.com을 방문한 사람에게 photos.example.com과 동일한 콘텐츠가 제공됩니다.
$ dig photographs.example.com 질의 결과는 다음과 같습니다:
photographs.example.com IN CNAME photos.example.com
photos.example.com IN A xx.xxx.x.xxx주의할 점은, CNAME 값은 오른쪽에 위치한 부분이라는 것입니다. 왼쪽은 별칭 이름, 즉 라벨(label)입니다.
또 다른 흔한 활용 사례는 www 서브도메인입니다. example.com을 구입했다면 www.example.com을 입력한 사용자에게도 같은 콘텐츠를 보여주고 싶을 것입니다.
참고로 example.com은 아펙스(apex), 루트(root), 내이키드(naked) 도메인 등으로 불립니다.
한 가지 방법은 example.com과 동일한 IP 주소를 가리키는 A 레코드를 하나 더 만드는 것입니다. 이것은 완전히 유효한 방법이며 실제 example.com도 이렇게 하고 있지만, 확장성이 떨어집니다. 만약 example.com이 가리키는 IP 주소를 변경해야 한다면 어떻게 될까요? www 서브도메인뿐 아니라 사용 중인 다른 모든 서브도메인의 레코드도 함께 수정해야 합니다.
반면 CNAME 레코드로 www.example.com이 example.com을 가리키도록 해두었다면, 루트 도메인만 업데이트하면 됩니다. 나머지 노드는 모두 루트를 가리키고 있기 때문입니다.
CNAME의 제약 사항
DNS 표준이 작성될 당시 몇 가지 사용 규칙이 정해졌습니다. RFC 1912와 RFC 2181에 따르면:
SOA와NS레코드는 반드시 루트 도메인에 존재해야 합니다.CNAME레코드는 단독으로만 존재해야 하며, 다른 리소스 레코드와 함께 사용할 수 없습니다(DNSSEC의SIG,NXT,KEY RR레코드는 예외).
두 규칙이 서로 충돌하기 때문에, 루트 도메인에는 CNAME을 사용할 수 없습니다.
여기서 중요한 점은 이것이 기술적 한계가 아니라 규약(contract)상의 한계라는 것입니다. 실제로 루트에 CNAME을 사용하는 것이 가능하지만, 예상된 동작 방식을 깨는 것이므로 예기치 않은 오류를 일으킬 수 있습니다.
Cloudflare는 루트 도메인에 CNAME을 사용한 후 Microsoft Exchange 메일 서버에서 겪은 문제를 사례로 소개한 바 있습니다:
도메인은 일반적으로 MX 레코드를 통해 이메일을 처리할 서버를 지정합니다. 문제는 Exchange 서버가 … 루트 레코드의 CNAME을 감지한 뒤 MX 레코드에 설정된 CNAME을 제대로 존중하지 않았다는 것입니다. Exchange를 탓할 수는 없습니다. 그들은 DNS 명세가 전제하는 규약에 따라 동작했을 뿐입니다.
이처럼 여러 서버 소프트웨어나 라이브러리에서 잠재적 문제가 발생할 수 있습니다. CNAME이 노드에서 유일한 레코드여야 한다는 표준이 있기 때문에, 다른 레코드를 찾지 않습니다. 따라서 나머지 레코드들은 경고나 에러 메시지 없이 조용히 무시됩니다. 이메일 수신을 위한 MX 레코드가 설정되어 있어도, CNAME이 먼저 평가되기 때문에 MX는 존재하지 않는 것처럼 무시됩니다. A 레코드가 있어도 마찬가지입니다. CNAME이 우선하며 A 레코드는 읽히지 않습니다.
현대의 인터넷 환경
그런데 왜 이것이 문제일까요? 애초에 루트 도메인에 CNAME을 쓰고 싶어지는 경우가 있을까요? 콘텐츠를 호스팅하는 웹 서버의 IP 주소를 찾는 경로의 끝은 루트 도메인이니 말입니다.
그러나 현대 인터넷 환경에서는 상황이 다릅니다. DNS 표준이 작성되던 시절과 세상은 많이 달라졌습니다.
예를 들어 Heroku 같은 PaaS(Platform as a Service) 제공사를 선택해 그들의 웹 서버에 콘텐츠를 저장할 수 있습니다. 콘텐츠는 내가 통제하지만 인프라는 통제할 수 없고, 네트워크 유지 보수라는 무거운 작업은 PaaS 제공사가 대신 처리합니다. 이들은 보통 자신들 루트 도메인의 서브도메인 형태로 URL(my-app.herokuapp.com)을 제공하며, 콘텐츠가 올라간 웹 서버의 IP 주소를 확인할 수 있게 해주지만, 그 IP는 전적으로 PaaS 제공사의 통제 하에 있으며 사전 통보 없이 얼마든지 변경됩니다.
PaaS 제공사가 백엔드를 변경하는 규모와 빈도를 고려하면, 루트 도메인의 A 레코드를 고정된 단일 IP 주소로 유지하는 것은 매우 어렵습니다. 이상적으로는 이렇게 설정하고 싶을 것입니다:
example.com IN CNAME my-app.herokuapp.com.
www.example.com IN CNAME my-app.herokuapp.com.이렇게 하면 Heroku(또는 선택한 호스팅 업체)가 CNAME이 가리키는 A 레코드를 알아서 갱신해 주고, 내 쪽에서는 아무 변경도 할 필요가 없습니다. 하지만 이미 알고 있듯이 이것은 DNS 명세를 위반하므로 매우 위험한 방법입니다.
example.com에서 www.example.com으로 301/302 리다이렉트를 걸 수도 있습니다. 그러나 이 방식은 리다이렉트가 웹 서버에서 처리되느냐(그렇다면 결국 그 웹 서버를 가리키는 고정 A 레코드가 필요한 문제는 그대로 남습니다), 혹은 DNS 제공사의 커스텀 리다이렉트로 처리되느냐(HTTPS 연동이 복잡해집니다)의 딜레마에 부딪힙니다.
게다가 URL 표시줄에 보이는 도메인이 바뀌는 부작용도 있어, 원치 않는 경우가 많습니다. 이 방법은 본래 웹사이트가 영구적으로 이동했거나 SEO 순위를 유지하려는 상황을 위한 것이지, 끊임없이 변하는 복잡한 백엔드를 확장 가능하게 가리키는 우리 문제의 해답이 아닙니다.
해결책
이 문제를 우회하기 위해 여러 DNS 제공사가 자체 솔루션을 개발했습니다:
- DNSimple의
ALIAS - DNS Made Easy의
ANAME - easyDNS의
ANAME - Cloudflare의 (가상)
CNAME
이들은 모두 CNAME과 같은 동작을 하면서 단점은 없는 가상 레코드 타입입니다. 구현 방식은 제공사마다 조금씩 다르지만, 큰 그림에서는 DNS 서버가 이 가상 레코드 타입을 만나면 DNS 리졸버처럼 동작합니다. 별칭이 만든 체인을 따라가다가 A 레코드(하나 이상)로 수렴되면, 그 A 레코드들을 가져와 반환합니다. 이렇게 CNAME 체인이 반환된 A 레코드로 '평탄화(flattening)'되며, 질의를 보낸 쪽에서는 구분이 불가능합니다. 질의는 순수한 A 레코드만 보게 되므로 DNS 명세를 위반하지 않고, CNAME의 어떤 단점도 갖지 않습니다.
이러한 가상 레코드는 루트에서 다른 레코드와 나란히 놓여도 의도치 않은 동작에 대한 걱정이 없습니다. 또한 제공사가 CNAME 체인을 따라가며 DNS를 조회하는 방식에 따라, 이전 조회 결과를 캐싱함으로써 성능상 이점을 얻기도 합니다.
DNSimple을 사용한다면 다음과 같이 설정할 수 있습니다. 이 방식은 도메인 별칭의 모든 장점을 누리면서도 루트 레벨 사용의 위험은 피할 수 있습니다.
example.com IN ALIAS my-app.herokuapp.com.
www.example.com IN CNAME my-app.herokuapp.com.읽어주셔서 감사합니다!
언제나처럼 잘못된 부분에 대한 정정이나 추가 의견은 언제든 환영합니다.
참고 자료
- What is a DNS Server (DNS 서버란 무엇인가)
- Set Up a DNS Name Server (DNS 네임서버 구축하기)
- DNSimple 지원 문서 및 ALIAS 블로그
- Cloudflare 지원 문서 및 CNAME 블로그
digHowTo- Stack Overflow / StackExchange의 여러 유용한 게시글
- Wikipedia의 잘 정리된 관련 문서
- Netlify 블로그 'To www or not www'