DNS 레코드와 실습
A·AAAA·CNAME·MX·NS·TXT 레코드의 의미와 제약을 익히고 nslookup·dig으로 응답과 TTL을 확인합니다.
DNS 서버가 도메인에 대한 정보를 저장한다는 것을 알았습니다.
이제 그 정보가 어떤 리소스 레코드(Resource Record) 형태로 표현되는지, 그리고 nslookup과 dig으로 직접 확인하는 방법을 살펴보겠습니다.
주요 DNS 레코드 유형
DNS 레코드는 “도메인 이름에 연결된 데이터”입니다.
표준적인 리소스 레코드는 보통 이름, TTL, 클래스, 타입, 데이터로 읽습니다.
예를 들어 example.com. 3600 IN A 93.184.216.34는 이름·TTL·클래스·타입·주소 순서입니다.
가장 자주 만나는 레코드 유형은 아래와 같습니다.
DNS · 레코드 읽기
이름과 TYPE을 먼저 정하고 값과 제약을 읽는다
A·AAAA의 주소, CNAME의 별칭, MX·NS의 서버 이름은 서로 다른 데이터입니다. 아래 이름·주소는 형식 예이며 TTL·클래스 등은 생략했습니다. SOA는 긴 필드 중 일부만 표시합니다.
| 타입 | 역할과 형식 예 | 제약·확인 |
|---|---|---|
| A | 이름 → IPv4 주소 — example.com. A 93.184.216.34 | 하나의 이름에 여러 A가 있을 수 있음 |
| AAAA | 이름 → IPv6 주소 — example.com. AAAA 2606:2800:220:1:: | IPv6 주소용 레코드 |
| CNAME | 별칭 이름 → canonical name — www CNAME example.com. | 같은 이름에 일반 레코드와 공존 불가 |
| MX | 메일 교환 서버 지정 — example.com. MX 10 mail.example.com. | 숫자가 낮을수록 우선순위가 높음 |
| NS | 영역의 권한 네임서버 지정 — example.com. NS ns1.example.com. | 위임과 권한 서버 확인에 사용 |
| TXT | 텍스트 기반 정책/검증 정보 — v=spf1 include:_spf.example.net -all | SPF, DKIM, DMARC 등 형식별 규칙 확인 필요 |
| SRV | 서비스 위치와 포트 지정 — _sip._tcp.example.com. SRV 10 60 5060 host.example.com. | 지원하는 프로토콜에서만 의미가 있음 |
| SOA | 영역 관리 메타데이터 (일부) — ns1.example.com. hostmaster.example.com. | serial, refresh, retry, expire 포함 |
| PTR | 역방향 이름 → canonical name — 34.216.184.93.in-addr.arpa. PTR ... | IP 소유자가 관리하는 역방향 영역 필요 |
| CAA | 인증서 발급 가능한 CA 제한 — example.com. CAA 0 issue "letsencrypt.org" | CA의 오발급 위험을 줄이는 정책 |
- A
- 역할과 형식 예: 이름 → IPv4 주소 — example.com. A 93.184.216.34제약·확인: 하나의 이름에 여러 A가 있을 수 있음
- AAAA
- 역할과 형식 예: 이름 → IPv6 주소 — example.com. AAAA 2606:2800:220:1::제약·확인: IPv6 주소용 레코드
- CNAME
- 역할과 형식 예: 별칭 이름 → canonical name — www CNAME example.com.제약·확인: 같은 이름에 일반 레코드와 공존 불가
- MX
- 역할과 형식 예: 메일 교환 서버 지정 — example.com. MX 10 mail.example.com.제약·확인: 숫자가 낮을수록 우선순위가 높음
- NS
- 역할과 형식 예: 영역의 권한 네임서버 지정 — example.com. NS ns1.example.com.제약·확인: 위임과 권한 서버 확인에 사용
- TXT
- 역할과 형식 예: 텍스트 기반 정책/검증 정보 — v=spf1 include:_spf.example.net -all제약·확인: SPF, DKIM, DMARC 등 형식별 규칙 확인 필요
- SRV
- 역할과 형식 예: 서비스 위치와 포트 지정 — _sip._tcp.example.com. SRV 10 60 5060 host.example.com.제약·확인: 지원하는 프로토콜에서만 의미가 있음
- SOA
- 역할과 형식 예: 영역 관리 메타데이터 (일부) — ns1.example.com. hostmaster.example.com.제약·확인: serial, refresh, retry, expire 포함
- PTR
- 역할과 형식 예: 역방향 이름 → canonical name — 34.216.184.93.in-addr.arpa. PTR ...제약·확인: IP 소유자가 관리하는 역방향 영역 필요
- CAA
- 역할과 형식 예: 인증서 발급 가능한 CA 제한 — example.com. CAA 0 issue "letsencrypt.org"제약·확인: CA의 오발급 위험을 줄이는 정책
주소와 이름은 형식 예시입니다. 실제 질의에서는 owner name과 TYPE을 먼저 고정하고 응답의 TTL·권한 플래그를 함께 읽습니다.
예시
아래는 직접 만든 고정 응답 조각이며 실제 dig 실행 결과가 아닙니다. 두 레코드를 읽어 마지막 주소가 어느 이름의 값인지 추적해 보세요.
www.example.com. 300 IN CNAME app.example.com.
app.example.com. 60 IN A 192.0.2.44첫 줄의 owner는 www.example.com, TYPE은 CNAME, 값은 app.example.com이라는 이름입니다. 두 번째 줄의 owner는 app.example.com, TYPE은 A, 값은 IPv4 주소입니다. 별칭 자체를 IP 주소처럼 사용하거나, 다른 owner에 있는 A를 CNAME과 같은 이름에 공존하는 A로 읽지 않습니다. 두 TTL도 각각의 레코드 재사용 한도이므로 반드시 같은 값일 필요는 없습니다.
CNAME의 제약과 대안
CNAME은 별칭을 만들 때 편하지만, 같은 이름에 다른 일반 레코드와 함께 둘 수 없습니다.
예를 들어 zone apex인 example.com에는 보통 SOA와 NS가 반드시 필요하므로 표준 DNS 관점에서 example.com CNAME ... 형태는 맞지 않습니다.
클라우드 DNS 서비스의 ALIAS, ANAME, CNAME flattening, Route 53 Alias 같은 기능은 이 제약을 우회하기 위한 제공자별 기능입니다.
이것들은 표준 CNAME 레코드라기보다 권한 DNS 서버가 대상 이름을 해석한 뒤 A/AAAA 응답처럼 돌려주는 방식에 가깝습니다.
MX 레코드와 이메일 보안 레코드
MX 레코드는 메일을 어느 서버로 전달할지 알려줍니다.
MX의 숫자는 “선호도(preference)”이며, 낮은 숫자가 먼저 시도됩니다.
같은 선호도의 MX가 여러 개라면 메일 전송 서버는 그 후보들을 나누어 시도할 수 있습니다.
이메일 보안에서는 TXT 레코드를 정책 저장소처럼 많이 사용합니다.
단, TXT는 단순한 문자열 컨테이너일 뿐이고, SPF/DKIM/DMARC는 각각 별도 규칙을 가진 프로토콜입니다.
-
SPF — DNS 위치 예시:
example.com TXT "v=spf1 ..."; 하는 일: envelope sender 도메인의 허용 발신원 선언; 자주 나는 실수: 같은 이름에 SPF 레코드를 여러 개 게시 -
DKIM — DNS 위치 예시:
selector._domainkey.example.com; 하는 일: 공개키로 메일 서명 검증; 자주 나는 실수: selector 이름이나 긴 TXT 문자열 오류 -
DMARC — DNS 위치 예시:
_dmarc.example.com TXT "v=DMARC1"; 하는 일: SPF/DKIM alignment와 정책, 리포트 주소 선언; 자주 나는 실수: SPF/DKIM과 From 도메인 alignment 혼동
레코드 조건을 바꾸어 판단하기
위 예시에 www.example.com. 300 IN A 192.0.2.45를 추가하면 표준 CNAME 규칙에 맞을까요? 그리고 example.com의 MX가 10 mail-a.example.com과 20 mail-b.example.com으로 주어지고 둘 모두 사용할 수 있다면 어느 것을 먼저 시도할까요? 첫 MX의 선호도만 30으로 바꾼 경우도 판단하세요.
별칭과 MX 선호도의 풀이
CNAME의 owner인 www.example.com에 일반 A까지 추가하면 같은 이름의 공존 제약을 위반합니다. app.example.com의 A를 유지하는 것과는 다른 상황입니다. DNSSEC에 필요한 서명 관련 레코드의 예외를 일반 A·MX 공존 허용으로 넓히지는 않습니다. MX는 원래 조건에서 선호도가 10인 mail-a를 먼저 시도하고, 변경한 조건에서는 선호도가 20인 mail-b를 먼저 시도합니다. 이 숫자는 포트나 메시지 우선순위가 아니라 MX 대상 선택의 선호도입니다. mail-a를 사용할 수 없으면 다른 후보를 시도할 수 있으므로 숫자가 낮다고 전달 성공을 보장하지는 않습니다. RFC2181의 CNAME·MX 제약을 함께 확인할 수 있습니다.
nslookup과 dig 실습
DNS 레코드를 직접 조회할 때는 nslookup과 dig을 많이 사용합니다.
nslookup은 기본 확인에 편하고, dig은 응답 섹션, 플래그, TTL, 권한 서버 추적을 더 자세히 보여줍니다.
dig·nslookup이 설치된 터미널에서 해당 명령 하나씩 실행합니다. 공개 도메인의 레코드는 변경될 수 있으므로 위에 적힌 주소나 레코드가 지금도 같은 출력으로 나온다는 전제는 없습니다. +short는 값만 빠르게 볼 때 쓰고, 응답의 상태·TTL·AA 플래그를 판단할 때는 전체 출력을 읽습니다. dig +trace는 도구가 각 위임 서버에 직접 질의하는 모드라 지정된 재귀 리졸버 한 곳의 응답을 보는 것과 접근 경로가 다릅니다.
# 기본 A 레코드 조회
nslookup example.com
# 특정 레코드 유형 조회
nslookup -type=MX example.com
nslookup -type=TXT example.com
nslookup -type=NS example.com
nslookup -type=AAAA example.com
# 특정 DNS 서버를 지정하여 조회
nslookup example.com 1.1.1.1
# 역방향 DNS 조회
nslookup 93.184.216.34# A 레코드 조회
dig example.com A
# 특정 레코드 유형 조회
dig example.com MX
dig example.com NS
dig example.com TXT
dig example.com AAAA
# 간결한 출력
dig +short example.com A
# 특정 리졸버 지정
dig @1.1.1.1 example.com A
# 권한 서버 경로 추적
dig +trace example.com
# 역방향 DNS
dig -x 93.184.216.34Non-authoritative answer는 해당 질의에 대한 권한 있는 답변(AA)이 아니라는 뜻이며, 재귀 리졸버의 응답에서 흔히 보입니다. 오래된 캐시라는 뜻은 아니므로 원본 상태는 권한 NS 직접 조회와 함께 확인합니다.
TTL과 DNS 캐시 동작
DNS 응답의 TTL(Time To Live)은 해당 레코드를 캐시에 얼마나 오래 보관할 수 있는지 초 단위로 나타냅니다.
TTL이 길면 반복 질의가 줄어 안정적이지만 변경 반영이 느리고, TTL이 짧으면 전환은 빠르지만 리졸버와 권한 서버 질의량이 늘어납니다.
import socket
def resolve_all(domain):
"""운영체제 리졸버를 통해 IPv4/IPv6 후보를 확인하는 간단한 예시"""
results = socket.getaddrinfo(domain, 80, type=socket.SOCK_STREAM)
seen = set()
for family, _, _, _, address in results:
ip = address[0]
if ip in seen:
continue
seen.add(ip)
version = "IPv6" if family == socket.AF_INET6 else "IPv4"
print(f"{domain:<24} {version:<4} {ip}")
resolve_all("example.com")캐시는 리졸버뿐 아니라 운영체제와 브라우저에도 존재합니다.
DNS 변경 후 예상과 다른 응답을 보면 브라우저 캐시, OS 캐시, 재귀 리졸버 캐시, 권한 서버 원본 레코드를 분리해서 확인해야 합니다.
존재하지 않는 이름(NXDOMAIN)도 SOA 정보와 함께 negative caching 될 수 있습니다. TTL은 일반 재사용 한도이며, RFC 8767의 serve-stale 정책을 쓰는 리졸버는 갱신 장애 때 만료된 답을 제한적으로 제공할 수 있습니다.
응답이 비었을 때 구분하기
dig의 ANSWER가 비었다는 사실 하나만으로 NXDOMAIN이라고 판단하지 않습니다. 예를 들어 이름은 있지만 요청한 AAAA가 없는 권한 응답은 NOERROR와 빈 ANSWER, AUTHORITY의 SOA로 나타날 수 있습니다. 이름 자체가 없다는 NXDOMAIN과 요청한 타입의 데이터가 없다는 NODATA는 다른 판단입니다. 빈 ANSWER와 NS 위임 정보만 받은 referral도 별도로 구별합니다. RFC2308의 부정 응답 구분을 참고하세요.
TTL을 읽는 독립 확인
60초짜리 항목을 저장한 뒤 15초가 지났고, 그 사이 새 응답을 받지 않았다고 가정합니다. 남은 TTL은 45초입니다. 같은 이름의 A 응답에 aa가 없다는 조건을 더하더라도, 이 사실만으로 45초가 잘못된 값이거나 응답이 만료됐다고 결론 내릴 수 없습니다. 반대로 AA가 있어도 그 주소의 웹 서버가 요청을 처리한다는 보장은 없습니다. 아래 dns_query.py는 주소 후보만 받으며 TTL이나 AA를 출력하지 않으므로, 그 프로그램의 숫자·상태를 dig의 레코드 메타데이터와 혼동하지 않습니다.
DNS 실습 체크리스트
-
기본 IP 조회 — 명령어:
dig example.com A; 확인 사항: ANSWER 섹션의 A 레코드와 TTL -
IPv6 조회 — 명령어:
dig example.com AAAA; 확인 사항: AAAA 응답 여부 -
메일 서버 확인 — 명령어:
dig example.com MX; 확인 사항: 낮은 preference 우선, MX target -
네임서버 확인 — 명령어:
dig example.com NS; 확인 사항: 위임된 권한 서버 -
이메일 인증 확인 — 명령어:
dig example.com TXT; 확인 사항: 이 명령은 apex TXT만 조회; DKIM·DMARC는 위의 별도 이름 조회 -
해석 경로 추적 — 명령어:
dig +trace example.com; 확인 사항: 루트 → TLD → 권한 서버 -
특정 리졸버 비교 — 명령어:
dig @1.1.1.1 example.com A; 확인 사항: 리졸버별 캐시/응답 차이 -
권한 서버 직접 확인 — 명령어:
dig @ns1.example.com name A; 확인 사항: 원본 레코드와 재귀 응답 차이 -
로컬 캐시 초기화 — 명령어:
ipconfig /flushdns; 확인 사항: Windows OS DNS 캐시 제거
다음 절에서는 DNS의 심화 활용과 실무에서 마주치는 보안 이슈를 살펴보겠습니다.