도입
많은 사람이 DNS를 “도메인을 IP로 바꿔 주는 것” 정도로 이해합니다. 물론 맞는 말이지만, 실제로는 그보다 훨씬 넓은 개념입니다.
DNS는 계층형 이름 공간, zone 단위의 권한 위임, authoritative server, recursive resolver, cache, TTL, negative caching, DNSSEC까지 포함한 분산 시스템입니다. 그래서 DNS를 제대로 이해하면 단순 조회를 넘어서 왜 어떤 이름은 바로 풀리고, 어떤 이름은 느리며, 어떤 응답은 캐시되고, 어떤 오류는 오래 남는지를 구조적으로 설명할 수 있게 됩니다.
필요성
인터넷 서비스는 IP 주소만으로 운영되지 않습니다. 사용자는 이름을 기억하고, 운영자는 인프라를 바꾸고, 서비스는 여러 서버로 분산되며, 메일은 별도 교환 서버를 가질 수 있습니다. 이 모든 것을 이름 기반으로 연결해 주는 시스템이 DNS입니다.
즉, DNS는 편의 기능이 아니라 이름과 인프라를 느슨하게 분리하는 핵심 계층입니다. 이 계층이 있기 때문에 서비스 운영자는 주소가 바뀌어도 이름을 유지할 수 있고, 클라이언트는 직접 IP를 관리하지 않아도 됩니다.
- 도메인은 살아 있는데 접속 결과가 서버마다 다르게 보이는 경우
- 응답 속도가 느린 이유가 네트워크가 아니라 캐시와 재질의 구조에 있는 경우
- 메일 라우팅이나 별칭 처리가 주소 조회와 다른 규칙으로 움직이는 경우
- NXDOMAIN, NODATA, SERVFAIL을 구분해야 하는 경우
- DNSSEC 때문에 정상이던 이름이 갑자기 검증 실패로 보이는 경우
정의
DNS는 크게 세 부분으로 볼 수 있습니다. 첫째는 이름이 배치되는 domain name space, 둘째는 그 이름에 연결된 정보를 담는 resource record, 셋째는 이 정보를 보관·질의·캐시하는 name server와 resolver입니다.
여기서 이름 공간은 트리 구조이며, 점(.)으로 구분된 label들이 위계적으로 연결됩니다. 실무적으로 보면 DNS는 “이름 → 값” 사전이라기보다, 위임과 권한이 분리된 이름 해석 시스템이라고 보는 편이 더 정확합니다.
핵심 원리
사용자 프로그램은 보통 직접 루트부터 질의하지 않습니다. 로컬의 stub resolver가 상위 recursive resolver에 질의하고, recursive resolver가 캐시에 답이 없을 때만 바깥으로 나갑니다.
이 구조 덕분에 클라이언트는 분산된 이름 공간의 내부 구조를 몰라도 됩니다. 복잡한 해석 절차는 resolver가 숨기고, 사용자는 이름만 주면 결과를 받는 형태로 단순화됩니다.
기본 구조
| 구성 요소 | 설명 | 실무 포인트 |
|---|---|---|
| Domain Name Space | label이 점으로 연결된 tree 구조의 이름 공간 | 이름 전체가 하나의 평면이 아니라 위계적 구조를 가짐 |
| Zone | 권한 있게 관리되는 이름 공간의 한 조각 | 운영 경계와 위임 경계를 이해할 때 핵심 |
| Delegation | 부모 zone이 child zone의 NS 정보를 넘겨 주는 과정 | 하나의 도메인이 여러 관리 단위로 나뉘는 이유 |
| Authoritative Server | 자신이 맡은 zone 내용을 local knowledge로 답하는 서버 | AA 비트와 referral 이해의 기준점 |
| Stub Resolver | 전체 해석을 직접 하지 못하고 상위 resolver에 의존하는 클라이언트 쪽 resolver | 일반 사용자 환경에서 가장 흔한 형태 |
| Recursive Resolver | 필요하면 다른 서버들을 따라가며 최종 답을 만들어 주는 resolver | 캐시와 성능의 핵심 위치 |
| TTL | RR이 캐시에 남을 수 있는 최대 시간 | 전파와 stale cache 오해를 풀 때 중요 |
패턴 1. 재귀 질의와 반복 질의
가장 흔한 흐름은 이렇습니다. 클라이언트의 stub resolver가 recursive query를 상위 resolver에 보냅니다. recursive resolver는 먼저 cache를 보고, 없으면 root hints를 바탕으로 적절한 서버를 찾기 시작합니다.
이후에는 root → TLD → authoritative server 방향으로 referral을 따라가며 더 구체적인 권한 서버를 찾습니다. authoritative answer를 얻으면 recursive resolver는 이를 cache에 저장하고 최종 답만 클라이언트에 돌려줍니다.
- stub resolver가 상위 recursive resolver에 질의한다.
- recursive resolver가 cache 또는 local data를 먼저 확인한다.
- 없으면 root 쪽 정보에서 시작해 적절한 서버를 찾는다.
- referral을 따라 더 가까운 authoritative server로 좁혀 간다.
- 최종 authoritative answer를 받으면 cache에 저장한다.
- recursive resolver가 클라이언트에 최종 답만 반환한다.
패턴 2. 메시지 구조와 RR
| 메시지 섹션 | 역할 | 실무 해석 |
|---|---|---|
| Header | 질의/응답 구분, opcode, rcode, flag, 섹션 개수 | RD, RA, AA, RCODE 해석의 중심 |
| Question | QNAME, QTYPE, QCLASS | 무엇을 물었는지의 원본 |
| Answer | 질문에 대한 직접 답 | 정답 RRset이 위치 |
| Authority | authority 정보 또는 referral의 핵심 정보 | NS RRset, SOA 등을 자주 보게 됨 |
| Additional | 질의와 관련된 추가 정보 | 추가 주소 정보, OPT pseudo-RR 등이 들어갈 수 있음 |
A: IPv4 호스트 주소AAAA: IPv6 주소NS: authoritative name server 지정CNAME: alias의 canonical name 지정SOA: zone of authority의 시작 정보MX: mail exchange 정보PTR: domain name pointerTXT: text strings
실무에서는 결과값 하나만 보는 대신, Answer가 비어 있는데 Authority에 SOA가 있는지, NS referral이 내려왔는지, Additional에 보조 주소 정보가 들어왔는지까지 같이 보는 편이 훨씬 정확합니다.
UDP, TCP, EDNS
많은 질의가 UDP로 오가기는 하지만, DNS는 UDP-only 프로토콜이 아닙니다. 현재 일반 목적 DNS 구현은 UDP와 TCP를 모두 지원해야 하며, 큰 응답이나 특정 상황에서는 TCP 경로가 중요해집니다.
또한 전통적인 DNS는 EDNS를 쓰지 않는 UDP 응답 크기에 512바이트 한계가 있습니다. 이 한계를 넘는 modern use case를 위해 EDNS(0)가 도입되었고, OPT pseudo-RR를 통해 더 큰 UDP payload, 추가 플래그, 확장된 RCODE 공간 등을 협상할 수 있습니다.
| 항목 | 설명 | 실무 포인트 |
|---|---|---|
| UDP | 짧고 빠른 질의/응답에 유리한 전송 경로 | 흔하지만 만능은 아님 |
| TCP | DNS 구현이 함께 지원해야 하는 전송 경로 | fallback과 큰 응답 처리에서 중요 |
| EDNS(0) | UDP payload 확장, 추가 flags/RCODE 확장, capability 광고 | modern DNS 확장의 핵심 |
패턴 3. 캐시와 TTL
TTL은 RR이 캐시에 남아 있을 수 있는 최대 시간입니다. 즉, authoritative server를 다시 물어보기 전까지 resolver가 기존 답을 재사용할 수 있는 상한선이라고 보면 됩니다.
또한 DNS는 positive answer만 캐시하지 않습니다. NXDOMAIN이나 NODATA 같은 negative response도 캐시합니다. 이 negative caching은 불필요한 질의를 줄이고 전체 트래픽을 줄이는 데 큰 역할을 합니다.
| 응답 유형 | 의미 | 캐시 관점 |
|---|---|---|
| Positive Answer | 질문한 RRset이 존재함 | TTL 동안 재사용 가능 |
| NXDOMAIN | 질의한 domain name 자체가 존재하지 않음 | 부정 응답도 캐시 가능 |
| NODATA | 이름은 유효하지만 요청한 type의 RR이 없음 | NXDOMAIN과 구분해서 봐야 함 |
부정 응답의 TTL은 SOA를 통해 전달되며, negative caching에서는 보통 SOA.MINIMUM과 SOA 자체 TTL의 최소값이 기준이 됩니다. 따라서 존재하지 않는 이름이나 타입에 대한 결과도 한동안 계속 재사용될 수 있습니다.
DNSSEC
DNSSEC는 DNS에 보안 레이어를 얹는 확장입니다. 핵심 가치는 이 응답이 정말 해당 zone이 제공한 데이터인가, 중간에 변조되지 않았는가를 검증할 수 있게 만드는 것입니다.
이 과정에는 DNSKEY, DS, RRSIG, NSEC 같은 RR과 프로토콜 수정이 사용됩니다. 다만 중요한 제한도 있습니다. DNSSEC는 기밀성을 제공하지 않으며, 설정이 틀리면 정상 zone이 검증 실패로 인해 오히려 도달 불가능해질 수 있습니다.
한계와 주의점
DNS는 실시간 단일 진실 저장소가 아닙니다. authoritative server가 값을 바꿔도 resolver의 cache가 살아 있으면 한동안 예전 답을 계속 볼 수 있습니다. 따라서 “authoritative에는 반영됐는데 사용자에겐 안 보인다”는 일이 충분히 발생할 수 있습니다.
또한 DNSSEC는 보안 이점을 주지만, 설정과 검증 복잡도를 높입니다. 잘못 서명된 zone, 끊어진 chain of trust, validation 실패는 정상 서비스도 보이지 않게 만들 수 있습니다. 그리고 포트 53이 열려 있다고 해서 그 트래픽이 자동으로 좋은 트래픽이거나 정상 DNS 트래픽이라는 뜻도 아닙니다.
- DNS는 cached distributed system이지 즉시 반영되는 중앙 DB가 아님
- authoritative와 recursive는 같은 역할이 아님
- UDP만 보면 DNS 전체를 이해한 것이 아님
- DNSSEC는 무결성과 원본 인증은 주지만 기밀성은 주지 않음
자주 하는 실수
- DNS를 “도메인 → 단일 IP” 매핑 정도로만 이해함
- authoritative server와 recursive resolver를 같은 것으로 봄
- TTL이 지나면 전 세계가 동시에 새 값을 본다고 착각함
- DNS는 UDP만 쓴다고 단정함
- NXDOMAIN과 NODATA를 같은 오류로 취급함
- DNSSEC가 DNS 내용을 암호화한다고 생각함
- 53번 포트가 열려 있으면 DNS가 정상이라고 단순화함
디버깅
요약
- ✅ DNS는 계층형 분산 이름 시스템이자 조회 프로토콜이다.
- ✅ 이름 공간은 tree 구조이고, 운영 권한은 zone 단위로 나뉜다.
- ✅ stub resolver는 보통 recursive resolver에 의존하고, recursive resolver는 referral을 따라 iterative resolution을 수행할 수 있다.
- ✅ DNS 메시지는 Header, Question, Answer, Authority, Additional의 5개 섹션으로 구성된다.
- ✅ DNS는 UDP만 쓰는 것이 아니며, 현대 구현은 UDP와 TCP를 모두 지원해야 한다.
- ✅ EDNS(0)는 더 큰 UDP payload와 추가 확장을 가능하게 한다.
- ✅ TTL과 negative caching은 DNS 성능과 전파 체감의 핵심이다.
- ✅ DNSSEC는 무결성과 원본 인증을 주지만 기밀성은 제공하지 않는다.