본문으로 건너뛰기

Vercel 계정 이관과 도메인 호출 과정 정리

·9 min read

프로젝트 완료 후 Vercel 계정을 회사(A계정)에서 클라이언트(B계정)로 이관하는 작업이 있었다. A계정에 이미 등록되어 있는 도메인을 B계정에도 추가하려다 동일 도메인 에러가 났고, "도메인 등록한 곳에서 TXT를 설정해달라"는 안내가 떴다.

우리 회사의 경우 주로 백엔드 개발자가 서버와 도메인을 연결하는 작업을 해왔기 때문에, 이걸 어디에서 어떻게 등록해야 할지 감이 없었다. 그래서 이번 기회에 도메인 등록 방법과, Vercel·AWS를 이용해 프로젝트를 배포했을 때 도메인이 어떻게 호출되는지를 정리해뒀다.

TXT가 왜 등장했나

TXT 레코드(도메인에 임의의 텍스트 값을 연결하기 위한 표준 DNS 레코드, RFC 1035)는 요즘 주로 두 가지 용도로 쓰인다. 하나는 이메일 인증(SPF·DKIM·DMARC), 다른 하나는 도메인 소유권 검증이다. 이번처럼 외부 서비스가 "이 도메인을 정말 너희가 다루느냐"를 확인할 때 TXT를 요구하는 경우가 흔하다.

Vercel은 한 도메인을 한 팀(또는 개인 계정)에만 연결할 수 있다. 다른 계정에 이미 등록된 도메인을 추가하려고 하면 _vercel.<도메인>vc-domain-verify=... 값의 TXT 레코드를 추가해 소유권을 증명하라고 요구한다. 검증이 끝나면 도메인 소유권이 자동으로 새 계정으로 이전된다. Vercel은 이 흐름을 "Add Existing → Verify & Claim"이라고 부른다.

도메인이 두 곳에 나뉘어 있었다

당시 운영 중인 도메인은 총 4개였다. 메인 도메인은 Route 53에 hosted zone(특정 도메인에 대한 DNS 레코드를 모아두는 AWS의 단위)을 만들어 권한 네임서버를 Route 53으로 위임해둔 상태였다. 나머지 3개(접근 시 메인 도메인으로 리다이렉트되는 보조 도메인)는 도메인을 구매했던 호스팅 사이트의 DNS 관리 화면에서 레코드를 관리하고 있었다.

그래서 TXT 등록은 두 곳에서 나눠서 했다.

  • 메인 도메인: Route 53 콘솔에 로그인해 등록된 도메인의 hosted zone으로 들어가 TXT를 추가했다. 복붙으로 간단히 끝났다. 김에 dev.~~~.~~~ 형태의 개발용 서브 도메인도 같은 hosted zone에서 함께 등록했다.
  • 나머지 3개: 호스팅 사이트의 DNS 고급 설정에 들어가 각 도메인에 TXT를 추가했다.

등록을 마치자 A계정 연결이 끊겼다

B계정에 도메인이 정상적으로 등록됨과 동시에, A계정에 기존 설정되어 있던 도메인 연결이 끊겨 있었다. 처음엔 "왜 둘 다 연결되어 있지 않지?" 싶었는데, Vercel의 동작이 그런 식이었다.

Vercel은 같은 도메인을 두 계정에 동시에 등록하는 것 자체를 막는다. _vercel.<도메인> TXT로 소유권을 증명하는 절차를 통과하면 도메인은 새 계정으로 이전되고, 그 시점에 원 계정의 연결은 끊긴다. 동시 사용이 허용되는 게 아니라 소유권이 옮겨가는 구조다.

Vercel·AWS 환경에서 도메인이 호출되는 흐름

여기까지 작업하면서 "그래서 사용자가 도메인을 입력하면 정확히 어떤 경로로 Vercel까지 도달하는가"가 궁금해졌다. 정리하면 이렇다.

핵심은 세 가지였다.

먼저 stub resolver(OS가 들고 있는 가벼운 DNS 클라이언트)와 recursive resolver(여러 권한 네임서버를 대신 순회해주는 DNS 서버, 보통 ISP가 운영)의 역할이 다르다는 점. 브라우저는 stub resolver에게 묻고, stub resolver는 recursive resolver에게 묻고, recursive resolver가 루트 → TLD → 권한 네임서버를 따라가며 답을 만들어 돌려준다.

다음으로 이 도메인은 레지스트라(도메인 판매처)에서 네임서버를 Route 53으로 위임해둔 상태라, 마지막 권한 네임서버가 Route 53 hosted zone이 된다는 점. Vercel이 알려준 레코드를 hosted zone에 등록해뒀기 때문에 결과적으로 Vercel edge(Vercel이 전 세계에 깔아둔 엣지 서버)로 트래픽이 흘러간다.

마지막으로 같은 Vercel edge IP라도 어떤 프로젝트로 보낼지는 Host 헤더로 결정된다는 점. edge가 HTTPS 요청의 Host 헤더를 읽어 어느 프로젝트 배포로 라우팅할지 정한다.

apex와 서브 도메인은 등록 레코드가 다르다

레코드를 등록하면서 한 가지 더 챙긴 것은 apex 도메인과 서브 도메인의 레코드 타입이 다르다는 점이다.

도메인 종류DNS 레코드비고
apex (example.com)A 레코드 (Vercel anycast IP)RFC 1034 — zone apex에 CNAME 사용 금지
서브 (dev.example.com, www.example.com)CNAME (*.vercel-dns.com 형태)프로젝트별 CNAME 값

apex(루트 도메인 example.com처럼 서브 도메인 없는 형태)에 CNAME을 쓸 수 없는 건 zone apex에는 CNAME과 다른 레코드를 공존시킬 수 없다는 RFC 1034 규칙 때문이다. 그래서 apex는 Vercel이 제공하는 anycast IP(전 세계 여러 위치에서 같은 IP로 응답할 수 있게 한 라우팅 방식)를 A 레코드로 등록하고, 서브 도메인은 Vercel이 알려준 프로젝트별 CNAME을 등록한다.

이번 작업으로 도메인이 두 곳에 분산돼 있는 우리 구성에서 어디에 무엇을 넣어야 하는지가 머릿속에 정리됐다. Vercel↔AWS 사이의 경계가 "Route 53 hosted zone에 어떤 레코드를 두느냐"로 깔끔하게 갈린다는 것도 같이 보였다.