도메인 이름이 IP 주소가 되기까지: DNS 조회 과정

브라우저에 주소를 입력하면 이름이 어떻게 IP 주소로 바뀌는지, 스텁 리졸버·재귀 리졸버·권한 서버·캐시의 역할과 A/AAAA 레코드, TTL을 RFC를 기준으로 정리했습니다.

개발네트워크

브라우저 주소창에 www.example.com을 입력하면 페이지가 뜨기 전에 먼저 풀어야 할 문제가 있습니다. 컴퓨터가 접속하려면 이름이 아니라 IP 주소가 필요합니다. 이름을 주소로 바꿔 주는 시스템이 DNS(Domain Name System)입니다. 그 조회 과정을 RFC에 나오는 용어대로 따라가 봅니다.

등장하는 구성 요소

DNS 용어를 정리한 RFC 9499를 따르면, 조회에는 대략 다음 역할이 등장합니다.

  • 스텁 리졸버(stub resolver): 스스로 조회를 끝까지 하지 못하는 리졸버입니다. 보통 운영체제나 라이브러리 안에 있고, 앱의 질문을 받아 재귀 리졸버에게 넘깁니다.
  • 재귀 리졸버(recursive resolver): 질문을 받아 필요한 서버들에 차례로 물어 최종 답을 찾아 주는 리졸버입니다. 통신사, 공개 DNS 서비스, 사내 네트워크, 가정용 공유기 등 여러 곳에서 운영됩니다. 받은 답을 캐시에 저장해 두었다가 재사용하는 것이 보통입니다.
  • 권한 서버(authoritative server): 어떤 영역(zone)의 내용을 직접 알고 있어서 다른 서버에 묻지 않고도 그 영역에 대한 질문에 답할 수 있는 서버입니다. example.com의 레코드를 최종적으로 알려 주는 곳이 여기입니다.
  • 캐시(cache): 전에 받은 답을 잠시 보관해 두는 곳입니다. 재귀 리졸버뿐 아니라 운영체제나 앱에도 있을 수 있습니다.

이름 공간의 꼭대기에는 루트가 있고, 그 아래 .com 같은 최상위 도메인(TLD), 그 아래 example.com 같은 도메인이 있습니다. 상위 영역은 하위 영역의 관리를 다른 서버에 위임(delegation) 하고, 그 서버가 어디인지 알려 주는 응답이 참조(referral) 입니다.

캐시가 비어 있을 때의 단순화한 경로

DNS 조회 흐름도. 클라이언트(브라우저·앱)가 스텁 리졸버에, 스텁 리졸버가 재귀 리졸버에 질문합니다. 재귀 리졸버의 캐시에 유효한 답이 있으면 바로 돌려줍니다. 캐시에 없으면 루트 서버(.com 서버를 참조), TLD 서버(example.com 서버를 참조), 권한 서버(A/AAAA 레코드로 답함) 순서로 묻고, 받은 답을 스텁 리졸버를 거쳐 클라이언트에 돌려줍니다.

그림: 모든 캐시가 비어 있다고 가정한 단순화한 경로입니다. 실제로는 앱, 운영체제, 재귀 리졸버의 캐시가 답하거나 중간 단계의 정보를 갖고 있을 수 있고, 그러면 경로가 짧아집니다.

아무것도 캐시에 없다고 가정하면, www.example.com의 주소를 찾는 과정은 다음과 같이 그릴 수 있습니다.

  1. 브라우저나 앱이 스텁 리졸버에게 www.example.com의 주소를 묻습니다.
  2. 스텁 리졸버는 설정된 재귀 리졸버에게 질문을 보냅니다.
  3. 재귀 리졸버는 루트 서버에 묻습니다. 루트 서버는 답을 주는 대신 “.com은 이 서버들이 맡고 있다”는 참조를 돌려줍니다.
  4. 재귀 리졸버는 .com 서버에 묻고, “example.com은 이 서버들이 맡고 있다”는 참조를 받습니다.
  5. 재귀 리졸버는 example.com의 권한 서버에 묻고, www.example.com의 A 또는 AAAA 레코드를 답으로 받습니다.
  6. 재귀 리졸버는 이 답을 캐시에 넣고 스텁 리졸버에 돌려주며, 스텁 리졸버는 앱에 전달합니다.

클라이언트는 재귀 리졸버에게 “최종 답을 찾아 달라”고 한 번 묻고, 재귀 리졸버가 참조를 따라가며 여러 서버에 묻는 구조입니다. RFC 1034는 이 두 방식을 재귀(recursive) 방식과 반복(iterative) 방식으로 구분해 설명하고, 리졸버가 캐시를 먼저 확인한 뒤 가장 가까운 것으로 알려진 서버부터 묻고 참조를 따라가는 알고리즘을 적어 두었습니다.

실제로는 이 그림과 다르다

위의 여섯 단계는 이해를 돕기 위한 모델입니다. 실제 조회는 여러 이유로 달라집니다.

  • 캐시가 먼저 답합니다. 재귀 리졸버에 유효한 답이 있으면 3~5단계 없이 바로 돌려줍니다. 한 리졸버를 많은 사용자가 함께 쓸 수 있으므로, 앞선 조회 덕분에 이름이 이미 캐시에 있을 수도 있습니다.
  • 중간 정보도 캐시됩니다. 재귀 리졸버는 .com을 맡은 서버 목록 같은 참조 정보도 보관하므로, 매번 루트부터 시작하지 않습니다.
  • 어디에 캐시가 있는지는 구현마다 다릅니다. 브라우저가 자체 캐시를 두는지, 운영체제가 캐시를 두는지, 앱이 운영체제 리졸버를 쓰는지 직접 DNS를 묻는지, hosts 파일을 먼저 보는지는 브라우저, 운영체제, 설정에 따라 다릅니다.
  • 왕복 횟수는 정해져 있지 않습니다. 캐시 상태, 응답 속도가 느린 서버에 대한 재시도, 여러 서버 중 선택, 별칭(CNAME)을 따라가는 추가 조회 등에 따라 네트워크 왕복 수는 0번부터 여러 번까지 달라집니다. “DNS 조회는 몇 번 왕복한다”는 고정된 숫자는 없습니다.

A 레코드와 AAAA 레코드

DNS가 돌려주는 주소는 레코드 종류로 구분됩니다.

  • A 레코드: IPv4 주소(32비트) 하나를 담습니다. 예: 192.0.2.1. RFC 1035에 정의되어 있습니다.
  • AAAA 레코드: IPv6 주소(128비트) 하나를 담습니다. 예: 2001:db8::1. RFC 3596에 정의되어 있습니다.

한 이름에 둘 다 있을 수도, 한쪽만 있을 수도 있습니다. 두 종류를 모두 받은 경우 어느 주소로 먼저 연결을 시도할지는 DNS가 아니라 클라이언트가 정합니다.

TTL: 캐시에 얼마나 둘 수 있는가

모든 레코드에는 TTL(Time To Live) 이 붙어 있습니다. RFC 1035는 TTL을 레코드를 캐시에 둘 수 있는 시간 간격(초)으로 정의하고, 이 시간이 지나면 정보의 출처에 다시 물어야 한다고 설명합니다. TTL이 0이면 진행 중인 트랜잭션에만 쓸 수 있고 캐시하지 않아야 한다는 뜻입니다.

TTL은 캐시에 둘 수 있는 가장 긴 기간이지, 반드시 그만큼 두어야 하는 기간은 아닙니다. 캐시는 그 전에 레코드를 버릴 수 있습니다. 다만 캐시된 사본이 만료되기 전까지는 그 사본으로 답할 수 있으므로, 레코드를 바꾼 직후에는 일부 사용자가 아직 옛 주소를 받을 수 있습니다.

DNS 조회는 접속이 아니다

DNS 조회가 끝나면 앱은 주소를 알게 될 뿐입니다. 웹 페이지를 받으려면 그 주소로 연결을 맺고(TCP나 QUIC), HTTPS라면 TLS로 암호화를 협상한 뒤 HTTP 요청을 보내는 별도의 단계가 이어집니다. 그래서 “사이트가 안 열린다”는 문제는 이름을 못 찾는 DNS 문제일 수도, 주소는 찾았지만 연결이나 서버 쪽에서 실패한 문제일 수도 있습니다.

참고한 RFC

RFC 1034와 1035는 DNS의 기초를 놓은 문서입니다. 이후 여러 RFC가 이 두 문서를 갱신하고 보완했으므로, 오늘날의 리졸버와 브라우저가 하는 일을 모두 담고 있지는 않습니다.

블로그로