getaddrinfo EAI_AGAIN 해결 (Node.js DNS)
getaddrinfo EAI_AGAIN는 Node 리졸버가 타임아웃한 것 — 죽은 이름이 아닙니다. 일시 오류와 진짜 버그를 3단계로 구분. 무료 즉시 진단으로 바로 확인.
내 도메인에 이 문제가 있는지 지금 확인
무료, 가입 불필요. 이 가이드가 다루는 항목을 바로 검사하고 조치 방법을 알려드립니다.
문제
Node가 Error: getaddrinfo EAI_AGAIN <hostname>을 던지고 요청이 프로세스를 못 떠납니다. 오류 객체에서 err.code는 EAI_AGAIN, err.syscall은 getaddrinfo. 핵심 단어는 again입니다: 리졸버가 지금 당장 답을 못 얻었다고 말하는 것 — 이름이 틀렸다는 게 아닙니다. 그 하나의 구분이 이 가이드의 전부입니다.
증상
axios,fetch,http.request,npm install,pg,mongoose호출이getaddrinfo EAI_AGAIN으로 거부됩니다.- 간헐적입니다 — 같은 코드가 재시도하면 성공하거나, 컨테이너 시작 때 실패하고 1분 뒤 되거나, 부하 때 실패하고 트래픽이 줄면 회복됩니다.
- 노트북에선 안 나는데 Docker·CI·쿠버네티스 안에서 나거나 — Alpine 기반 이미지에서만 납니다.
npm install이나 빌드 단계가 EAI_AGAIN으로 레지스트리에 못 닿다가 재실행하면 됩니다.
getaddrinfo EAI_AGAIN의 진짜 의미
Node는 소켓을 열기 전에 호스트명을 IP로 바꿔야 합니다. 그걸 dns.lookup()으로 하는데, 이건 libuv 스레드풀에서 운영체제의 getaddrinfo(3)를 호출합니다 — 셸이 쓰는 것과 같은 리졸버 경로로, /etc/resolv.conf와 /etc/nsswitch.conf를 따릅니다. http/https 위에 지은 거의 모든 것 — fetch, axios, DB 드라이버, npm — 이 이 경로를 씁니다.
EAI_AGAIN은 getaddrinfo가 **이름 해석의 일시적 실패(temporary failure in name resolution)**에 쓰는 코드입니다. “그런 이름 없음”이 아닙니다. 리졸버가 DNS 서버에 닿으려 했는데 제때 쓸 만한 답을 못 받았다는 뜻입니다 — 서버가 닿지 않거나, 과부하거나, 느리거나, 아직 거기 없는 것. 이 코드의 POSIX 계약은 명시적입니다: 조건은 일시적이고, 다시 시도하면 같은 조회가 성공할 수 있습니다.
그게 핵심이고, 형제 코드 ENOTFOUND(EAI_NONAME)의 정반대입니다. ENOTFOUND는 리졸버가 답했고 그 답이 “이 이름엔 주소가 없다”는 것. ENOTFOUND는 영구적이고 당신의 코드나 DNS 레코드에 삽니다. EAI_AGAIN은 일시적이고 DNS 서버로 가는 당신의 네트워크 경로에 삽니다. 둘을 헷갈리는 게 여기서 오후를 날리는 가장 흔한 방법입니다: 흔들리는 리졸버를 호스트명을 다르게 파싱해서 고칠 수 없고, 오타 난 호스트명을 재시도해서 고칠 수 없습니다.
상위 3가지 원인
- 리졸버가 닿지 않거나 타임아웃.
/etc/resolv.conf에 적힌 DNS 서버가 죽었거나, 방화벽·이그레스 규칙에 막혔거나, 프로세스가 아직 못 닿는 네트워크에 있습니다. 이게 기본 케이스입니다: 부팅 때 네트워크가 완전히 안 올라옴, VPN 미연결, DNS 서버 잠깐 과부하. 조회가 타임아웃하고 libc가 EAI_AGAIN을 반환하고, 잠시 뒤 됩니다. - Docker/Alpine과 musl의 병렬 조회. Alpine 이미지는 musl libc를 쓰는데, musl은 A와 AAAA 쿼리를 병렬로 내고 glibc보다 타임아웃에 엄격합니다. 컨테이너 네트워크 안에서 흔한 느리거나 손실 있는 리졸버를 상대로, 그건 glibc 호스트라면 조용히 성공했을 자리에 간헐적 EAI_AGAIN을 냅니다. 컨테이너의 생성된
/etc/resolv.conf가 네트워크 네임스페이스 안에서 닿지 않는 리졸버나, 앱 시작 순간 준비 안 된 것을 가리킬 수도 있습니다. 더 나쁜 건, 옛 musl은 경계 자체에 부정확했습니다: 정말로 존재하지 않는 이름이 Alpine에선 깔끔한 ENOTFOUND 대신 EAI_AGAIN으로 나올 수 있어, musl에선 코드만으로는 더 약한 신호입니다. - 쿠버네티스
ndots:5가 모든 조회를 증폭. 파드/etc/resolv.conf의 기본ndots:5는 점이 다섯 개 미만인 호스트명을 먼저 모든 검색 도메인에 시도한다는 뜻 — 그래서 외부 조회 하나가 진짜 조회 전에 여러 쿼리가 됩니다. 클러스터 DNS(CoreDNS)가 압박받고 있으면 그 여분 쿼리들이 전부 타임아웃해 부하 때 EAI_AGAIN으로 표면화됩니다. 해법은 흔히 완전 정규화된 이름(끝 점)이나 조정된ndots지, 애플리케이션 코드가 아닙니다.
EAI_AGAIN vs ENOTFOUND — 해법을 결정하는 분기
언제나 err.code부터 찍으세요. 어느 세계에 있는지 알려줍니다:
EAI_AGAIN— 답이 안 왔다. 일시적. 올바른 대응은 백오프를 둔 유한 재시도 더하기 리졸버 점검: resolv.conf에 어느 네임서버가 있나, 닿나, 뭔가(ndots·musl·이그레스 규칙)가 쿼리를 불리거나 떨구고 있나. 호스트명 조립 방식을 다시 쓰는 건 여기서 아무것도 안 고칩니다.ENOTFOUND— 답이 왔고 “그런 이름 없음”이었다. 영구적. 재시도는 더 빨리 실패할 뿐. 버그는 잘못된 호스트명, 미설정 환경변수, 빠진 DNS 레코드입니다. (그건 전용 가이드가 따로 있습니다.)
glibc 시스템에선 둘이 깔끔히 갈립니다. musl/Alpine에선 EAI_AGAIN을 약간 의심하세요 — 순수 일시적이라 넘겨짚기 전에, 이름이 건강한 리졸버에서 실제로 해석되는지 확인하세요.
DechoNet으로 진단하기
- DNS 점검 — 오류의 정확한 호스트명으로, 당신 인프라 바깥에서 돌려보세요. DechoNet이 유효한 A/AAAA 레코드를 반환하면 이름은 멀쩡하고 문제는 당신의 리졸버 경로입니다: 컨테이너·호스트가 쓰는 DNS 서버가 닿지 않거나 느린 것이지 이름이 아닙니다. 그러면 ENOTFOUND류 원인이 곧바로 배제되고
resolv.conf·컨테이너 네트워크·ndots를 가리킵니다. DechoNet도 해석 못 하면, EAI_AGAIN 가면을 쓴 진짜 이름 문제일 수 있습니다(특히 Alpine). - 전파 점검 — 레코드가 새것이거나 방금 바뀌었으면 여러 리졸버를 한 번에 조회하세요. 일부는 답하고 일부는 타임아웃하면 특정 네트워크에선 EAI_AGAIN처럼 보입니다. 그건 전파·도달성이지 당신 앱이 아닙니다.
해결 체크리스트
-
err.code를 찍어 정말ENOTFOUND가 아닌EAI_AGAIN인지 확인하세요. 해법이 전적으로 여기서 갈립니다. - 호스트명에 외부 DNS 점검을 돌리세요. 밖에선 잘 해석됨 → 이름은 좋고, 문제는 코드가 아니라 당신의 리졸버 경로.
- 실패하는 환경(컨테이너 안, CI 러너, 파드)에서
/etc/resolv.conf를 확인하세요. 네임서버가 거기서 닿는지 — 노트북이 아니라 — 확인. - Docker에선 확실한 리졸버를 가리키세요: 실행 시
--dns 8.8.8.8, 또는 데몬 설정의dns항목. 빌드 시 EAI_AGAIN은 Dockerfile이 아니라 Docker 데몬에 DNS를 설정하세요. - Alpine에선 느린 리졸버를 상대로 한 musl의 병렬 조회가 원인인지 따져보세요. 더 능력 있는 베이스 이미지나 닿는 로컬 리졸버가 간헐성을 없애는 경우가 많습니다.
- 쿠버네티스에선
ndots를 확인하세요 — 완전 정규화된 호스트명(끝 점)이나dnsConfig오버라이드가 조회 하나가 다섯으로 부채질되는 걸 막습니다. - 진짜 일시적 케이스엔 유한한 지수 백오프 재시도를 더하세요 — 몇 번, 지연을 늘려가며 — 고장난 리졸버를 두들기는 무한 타이트 루프가 아니라.
언제 에스컬레이션할까
- 외부 DNS 점검은 이름을 해석하는데 플랫폼 안의 모든 재시도가 여전히 EAI_AGAIN을 반환하면, 제약은 그 환경의 DNS나 이그레스입니다 — 클러스터·CI·VPC 네트워크를 운영하는 쪽에 에스컬레이션하세요. 그들이 설정한 리졸버가 닿지 않거나 과부하고, 어떤 애플리케이션 변경도 거기 못 미칩니다.
- 실패가 부하와 상관관계를 보이고 클러스터 DNS(CoreDNS)가 리졸버라면, 운영자에게 타이밍과 쿼리 양을 넘기세요 — 과소 프로비저닝됐거나
ndots로 증폭된 클러스터 DNS는 앱이 아니라 인프라 수정입니다.
관련 도구
관련 가이드
가이드 공유