개발 학습 실습실

이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.

공부 › 네트워크 › 주소와 이름

DNS

도메인 이름의 주소는 누가 알고 있고, 바꾸면 언제 반영될까

컴퓨터는 shop.example 같은 이름으로는 접속할 수 없고 IP 주소가 있어야 합니다. 이름을 주소로 바꿔 주는 것이 DNS입니다. 답을 아는 서버는 한 곳이 아니라 여러 단계로 나뉘어 있고, 한 번 받은 답은 정해진 시간(TTL) 동안 캐시에 남아 다시 묻지 않습니다.

일부만 실행으로 확인 · 127.0.0.1에 띄운 시험용 네임 서버와 리졸버로 서른두 가지 조합을 실제 DNS 메시지로 실행해 대조. 레코드의 풀이는 Node.js 24의 c-ares와 대조했고, 리졸버와 캐시의 동작은 RFC 1034와 1035의 절차를 재현한 것

이 실습에 나오는 개념

DNS
도메인 이름(example.com)을 컴퓨터가 통신에 사용하는 IP 주소로 바꿔 주는 시스템이다. 브라우저에 주소를 입력하면 먼저 DNS에 그 이름의 IP 주소를 물어본 뒤 해당 IP로 접속한다. 조회 결과는 일정 시간 동안 캐시된다.
DNS 레코드
도메인의 네임 서버가 이름마다 가지고 있는 한 줄의 정보로, 이름, 종류, 값, TTL로 이루어진다. A는 이름에 IPv4 주소를, AAAA는 IPv6 주소를 연결한다. CNAME은 이름을 다른 이름의 별명으로 만들며, 별명을 물으면 진짜 이름으로 한 번 더 찾아야 주소가 나온다. MX는 그 도메인 앞으로 온 메일을 받는 서버의 이름과 우선순위를 알려 주고, 숫자가 작은 서버부터 시도한다.
재귀 리졸버와 권한 있는 네임 서버
권한 있는 네임 서버는 어떤 도메인의 레코드 원본을 가지고 있어 그 도메인에 대한 질문에 직접 답하는 서버다. 재귀 리졸버는 사용자의 컴퓨터를 대신해 답을 찾아다 주는 서버로, 루트 서버에서 시작해 TLD 서버, 권한 있는 네임 서버의 순서로 물어 답을 얻는다. 루트 서버와 TLD 서버는 답 대신 다음에 물어볼 서버를 알려 주는데, 이런 응답을 리퍼럴(referral)이라고 한다. 그렇게 알려 줄 수 있는 것은 위쪽 영역에 아래쪽 영역을 맡은 네임 서버가 적혀 있기 때문이며, 이렇게 아래쪽 영역을 따로 떼어 맡기는 것을 위임(delegation)이라고 한다. 사용자의 컴퓨터는 재귀 리졸버 하나에게만 물으며, 그 주소는 보통 통신사나 공유기가 네트워크 설정으로 알려 준다.
DNS 캐시와 TTL
DNS에서 받은 답을 다시 묻지 않도록 기억해 두는 것이 캐시이고, 그 답을 얼마 동안 기억해도 되는지를 초 단위로 적은 숫자가 TTL이다. TTL은 레코드를 관리하는 쪽이 정해 레코드에 붙인다. 캐시는 브라우저, 운영체제, 재귀 리졸버에 각각 있으며, TTL이 지나면 답을 버리고 다시 묻는다. 그래서 레코드를 바꿔도 이미 캐시에 들어간 답은 TTL이 끝날 때까지 쓰이고, 사용자마다 새 값을 받는 시점이 다르다.

이렇게 바꿔 보세요

처음 설정으로 실행하면

  1. 브라우저가 shop.example에 접속하려면 IP 주소가 필요합니다. 찾을 것은 shop.example의 A 레코드(IPv4 주소)입니다. 먼저 이 PC의 캐시(운영체제와 브라우저가 전에 받은 답을 기억해 둔 곳)를 봅니다. 처음 묻는 이름이라 없습니다.
  2. 이 PC가 재귀 리졸버에게 묻습니다. 재귀 리졸버는 답을 대신 찾아다 주는 DNS 서버로, 보통 통신사나 회사가 운영하며 그 주소는 네트워크 설정에 들어 있습니다. 리졸버도 먼저 자기 캐시를 봅니다. 없습니다. 리졸버가 처음부터 알고 있는 것은 루트 서버의 주소뿐입니다.
  3. 리졸버 → 루트 서버: 리졸버가 같은 질문을 루트 서버에 보냅니다. 루트 서버는 답을 가지고 있지 않습니다. 대신 이름의 맨 끝(.example)을 보고, .example로 끝나는 이름을 맡은 서버(TLD 서버)의 주소를 알려 줍니다. 이렇게 아래 서버에 맡겨 둔 것을 위임이라고 합니다.
  4. 리졸버 → .example 서버: 같은 질문을 다시 보냅니다. 이 서버도 답은 가지고 있지 않고, shop.example을 맡은 네임 서버의 주소를 알려 줍니다.
  5. 리졸버 → shop.example의 권한 있는 네임 서버: 이 도메인의 레코드 원본을 가진 서버입니다. 답을 줍니다: shop.example A 203.0.113.10, TTL 300초.
  6. 리졸버가 받은 레코드를 자기 캐시에 넣고 이 PC에 답을 돌려줍니다. 앞으로 300초 동안은 누가 같은 것을 물어도 캐시에서 답합니다. 오는 길에 알게 된 위임 정보도 함께 기억해 둡니다. 이 PC도 받은 답을 TTL 동안 캐시에 넣어 둡니다.
  7. 브라우저는 받은 주소(203.0.113.10)로 접속합니다.

실행 결과

코드

; shop.example의 권한 있는 네임 서버가 가진 레코드 (이름, TTL, 종류, 값)
shop.example.        300  IN  A      203.0.113.10
shop.example.        300  IN  AAAA   2001:db8::10
shop.example.        300  IN  MX     10 mail.shop.example.
www.shop.example.    300  IN  CNAME  shop.cdn.example.

; cdn.example의 권한 있는 네임 서버가 가진 레코드
shop.cdn.example.    300  IN  A      203.0.113.80

// 묻는 쪽 (Node.js, 파일 이름은 ask.mjs). 네트워크 설정에 있는 재귀 리졸버에게 묻고 답을 받는다
import { Resolver } from 'node:dns/promises';
console.log(await new Resolver().resolve4('shop.example', { ttl: true }));

이 모형의 전제

127.0.0.1에 루트 서버, .example 서버, 권한 있는 네임 서버 둘, 재귀 리졸버 역할을 하는 시험용 프로그램을 띄워 실제 DNS 메시지를 주고받게 하고, 서른두 가지 조합의 답, 질문 횟수, 묻는 순서, 바꾼 값이 반영되는지를 대조했습니다. 외부 DNS에는 묻지 않았습니다. 다만 이 시험용 네임 서버와 리졸버, PC 쪽 캐시는 표준의 절차(RFC 1034 4.3.2절 네임 서버의 응답, 5.3.3절 리졸버의 절차, RFC 1035 6.1.3절 캐시의 TTL)를 따라 이 실습을 위해 만든 것입니다. 그래서 "루트부터 차례로 묻는다", "TTL 동안 캐시의 답을 쓴다", "TTL이 지나도 위임 정보가 남아 있으면 권한 있는 네임 서버에 바로 묻는다"는 동작은 표준의 절차를 재현해 확인한 것이고, 실제로 운영되는 리졸버 제품이나 운영체제의 캐시와 대조한 것은 아닙니다. 독립된 구현으로 확인한 부분은 레코드의 내용입니다. 조합마다 같은 질문을 Node.js 24의 dns.Resolver(c-ares)로도 보내, 시험용 서버의 응답을 c-ares가 풀이한 A, AAAA, CNAME, MX의 값이 같은지 대조했습니다. Node.js의 dns.Resolver는 스스로 캐시하지 않고 매번 다시 묻는다는 것도 확인했습니다. 시간은 실제로 기다려 만들었습니다. 실행에서는 레코드의 TTL을 4초로 두고 1.2초 뒤(TTL이 남음)와 5.2초 뒤(TTL이 지남)에 다시 물었으며, 화면의 300초, 120초, 400초, 위임 정보의 172800초는 같은 상황을 흔히 보는 크기의 숫자로 적은 예입니다. 레코드의 뜻은 RFC 1035 3.3절과 3.4.1절(A, CNAME, MX), RFC 3596(AAAA), CNAME을 만나면 진짜 이름으로 다시 찾는 것은 RFC 1034 3.6.2절을 따랐습니다. 실제 리졸버는 여러 루트 서버와 네임 서버 가운데 하나를 고르고, 질문에 이름의 일부만 실어 보내거나(RFC 9156) 없다는 답도 캐시하는 등 더 많은 일을 합니다. 브라우저와 운영체제가 TTL을 그대로 지키지 않고 더 짧게 또는 더 길게 기억하는 경우도 있습니다. 주소는 모두 문서용으로 예약된 대역입니다.

앞 실습: URL의 구조 · 다음 실습: IP 주소와 서브넷

이 실습에 나오는 개념

이 실습에서 보는 것

설정

코드


      
    

그림

실행 비교

이렇게 바꿔 보세요