빠른 비교
import { lookup } from "node:dns/promises";
import { resolve4, resolveMx } from "node:dns/promises";
const address = await lookup("example.com");
const aRecords = await resolve4("example.com");
const mxRecords = await resolveMx("example.com");| 목적 | 먼저 볼 API |
|---|---|
| Node 네트워크 연결과 같은 이름 해석 | dns.lookup() |
| A, AAAA, MX 같은 DNS record 조회 | dns.resolve*() |
| OS hosts 파일과 resolver 정책 반영 | lookup() |
| DNS 서버 질의 결과 자체 확인 | resolve4(), resolve6(), resolveMx() |
lookup 기준
dns.lookup()은 일반적인 DNS 질의 함수처럼 보이지만, 실제 목적은 Node의 네트워크 연결에서 쓰는 이름 해석 흐름에 가깝습니다. 운영체제의 name resolution을 따르므로 /etc/hosts, 로컬 resolver, OS 설정 영향을 받을 수 있습니다.
const { address, family } = await lookup("localhost");
console.log(address, family);HTTP client, TCP socket 연결 문제를 재현하려면 lookup() 결과를 먼저 보는 편이 자연스럽습니다. 애플리케이션이 실제 연결할 때 어떤 주소를 받을지 확인하는 데 가깝기 때문입니다.
resolve 기준
dns.resolve*() 계열은 DNS record 조회에 초점이 있습니다. A record, AAAA record, MX record, TXT record처럼 DNS 데이터 자체를 확인할 때 사용합니다.
const records = await resolve4("example.com");
const mailServers = await resolveMx("example.com");resolve 계열은 OS hosts 파일에 적은 임시 매핑을 그대로 확인하는 용도와 다릅니다. DNS 서버가 돌려주는 record를 보고 싶은지, Node 연결이 실제로 해석하는 주소를 보고 싶은지 먼저 나누어야 합니다.
언제 무엇을 쓸까
서비스가 특정 host에 연결하지 못하는 문제라면 lookup()으로 시작합니다. ENOTFOUND, IPv4/IPv6 선택, 로컬 hosts override, 컨테이너 DNS 설정처럼 실제 연결 경로와 맞닿아 있기 때문입니다.
try {
console.log(await lookup("api.internal"));
} catch (error) {
console.error(error.code);
}도메인 설정을 점검하거나 메일 서버, TXT 인증 record, CDN record를 확인하려면 resolve 계열이 맞습니다.
const txt = await import("node:dns/promises").then(({ resolveTxt }) =>
resolveTxt("example.com"),
);애플리케이션 코드에서 DNS 결과를 캐싱할 때는 TTL, 오류 정책, IPv4/IPv6 우선순위까지 같이 봐야 합니다. 단순히 한 번 resolve한 값을 오래 들고 있으면 장애 조치나 DNS 변경을 놓칠 수 있습니다.
주의할 점
lookup() 결과와 resolve4() 결과가 다를 수 있습니다. 하나가 맞고 하나가 틀렸다는 뜻이 아니라,
OS 이름 해석을 보는지 DNS record 질의를 보는지 기준이 다르다는 뜻입니다.
컨테이너와 서버리스 환경에서는 DNS 설정이 로컬 개발 머신과 다를 수 있습니다. 로컬에서 resolve4()가 정상이어도 런타임의 resolver 정책, 네트워크 격리, private DNS 구성 때문에 실제 연결은 실패할 수 있습니다. 연결 장애 분석에서는 같은 런타임 안에서 확인해야 합니다.
참고 링크
1 sources