이 에러가 뜨는 상황
Node.js 앱을 로컬에서 실행하는데 이런 에러가 나온다.
MongoServerSelectionError: connect ECONNREFUSED ::1:27017
at Topology.selectServer (/node_modules/mongoose/...)
at ...
또는 Python 쪽이라면:
pymongo.errors.ServerSelectionTimeoutError: localhost:27017: [Errno 111] Connection refused
분명히 mongod를 실행했다고 생각하는데 연결이 안 된다. mongodb://localhost:27017로 접속 시도하는데 왜 ::1(IPv6)로 가는지도 모르겠다. 이게 왜 생기는지, 어떻게 잡는지 순서대로 정리한다.
핵심 원인 세 가지
1. MongoDB 서비스가 실제로 안 돌고 있음
가장 기본적인 원인인데 의외로 많다. mongod 명령어를 쳤는데 포그라운드로 떠서 터미널 닫을 때 같이 죽는 경우, 또는 서비스 등록 없이 수동 실행했다가 시스템 재시작 후 안 뜨는 경우다.
# Linux/macOS — MongoDB 상태 확인
sudo systemctl status mongod # Linux (systemd)
brew services list | grep mongodb # macOS (Homebrew)
# 안 떠있으면 시작
sudo systemctl start mongod # Linux
brew services start mongodb-community # macOS
# 실제로 27017 포트 열려있는지 확인
netstat -tlnp | grep 27017 # Linux
lsof -i :27017 # macOS
포트 리스닝이 없으면 MongoDB가 안 뜬 것이다.
2. localhost가 ::1(IPv6)로 해석되는 문제
Node.js v17부터 DNS 리졸버가 IPv6를 우선한다. localhost를 DNS로 조회하면 ::1(IPv6)를 먼저 반환하는데, MongoDB가 IPv4(127.0.0.1)에서만 리스닝 중이면 연결이 거부된다.
에러 메시지의 ::1:27017이 바로 이 경우다.
빠른 확인: MongoDB가 IPv4로 리스닝하는지 확인
netstat -tlnp | grep 27017
# 결과 예시:
# tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN (IPv4만 리스닝)
# tcp6 0 0 :::27017 :::* LISTEN (IPv6도 리스닝)
3. bindIp 설정이 제한되어 있음
/etc/mongod.conf의 bindIp가 127.0.0.1로만 설정돼 있으면 IPv6(::1)로 오는 연결은 거부된다.
상황별 해결 방법
방법 1: 연결 문자열에서 localhost 대신 IP 직접 지정
가장 빠른 임시 해결책이다. localhost 대신 127.0.0.1을 명시한다.
// 변경 전
mongoose.connect('mongodb://localhost:27017/mydb');
// 변경 후
mongoose.connect('mongodb://127.0.0.1:27017/mydb');
# Python pymongo
from pymongo import MongoClient
# 변경 전
client = MongoClient('localhost', 27017)
# 변경 후
client = MongoClient('127.0.0.1', 27017)
localhost 대신 127.0.0.1을 쓰면 DNS 조회 없이 바로 IPv4로 연결한다. 많은 경우데 이것만으로 해결된다.
방법 2: MongoDB bindIp에 IPv6 추가
근본 해결을 원하면 MongoDB 설정에서 IPv6도 리스닝하도록 한다.
# /etc/mongod.conf
net:
port: 27017
bindIp: 127.0.0.1,::1 # IPv4, IPv6 모두 리스닝
설정 변경 후 재시작:
sudo systemctl restart mongod
방법 3: Docker로 MongoDB 실행 중인 경우
Docker로 MongoDB를 띄웠는데 포트 매핑을 빠뜨린 경우다.
# 잘못된 예 — 포트 매핑 없음
docker run -d --name mongo mongo:7
# 올바른 예 — 27017 포트 매핑
docker run -d --name mongo -p 27017:27017 mongo:7
Docker Compose라면:
services:
mongo:
image: mongo:7
ports:
- "27017:27017" # 이 줄이 없으면 호스트에서 접속 불가
volumes:
- mongo_data:/data/db
상황별 체크리스트
| 체크 항목 | 명령어 | 기대 결과 |
|---|---|---|
| MongoDB 프로세스 실행 중 | ps aux | grep mongod | mongod 프로세스 보임 |
| 27017 포트 리스닝 | lsof -i :27017 | mongod 프로세스가 27017 점유 |
| IPv4 리스닝 확인 | netstat -tlnp | grep 27017 | 127.0.0.1:27017 또는 0.0.0.0:27017 |
| Docker 포트 매핑 | docker ps | 0.0.0.0:27017->27017/tcp 확인 |
| 연결 테스트 (IPv4) | nc -zv 127.0.0.1 27017 | Connection succeeded |
| 연결 테스트 (IPv6) | nc -zv ::1 27017 | succeeded/failed 여부 확인 |
MongoDB 로그로 원인 확인
# 로그 실시간 확인
sudo tail -f /var/log/mongodb/mongod.log
# 최근 에러만
sudo grep -i error /var/log/mongodb/mongod.log | tail -20
로그에서 bind failed 또는 exception in initAndListen 같은 메시지가 보이면 포트 충돌이나 권한 문제다.
# 27017 포트 점유 프로세스 확인 (MongoDB 아닌 다른 프로세스일 수도 있음)
sudo lsof -i :27017
MongoServerError: Authentication Failed도 같이 나온다면
연결은 됐는데 인증에서 막히는 경우는 별개 이슈다. ECONNREFUSED(연결 거부)와 헷갈리기 쉬운데, 연결 거부는 TCP 자체가 안 되는 것이고 인증 실패는 연결 후 자격증명 검증 단계다.
인증 실패 에러:
MongoServerError: Authentication failed.
이 경우는 username/password 오류이거나 authSource 설정 문제다.
// authSource 명시
mongoose.connect('mongodb://user:pass@127.0.0.1:27017/mydb?authSource=admin');
마무리
ECONNREFUSED ::1:27017 에러는 90%가 두 가지 원인 중 하나다:
- MongoDB가 실제로 안 떠있음
- localhost가 IPv6로 해석되는데 MongoDB는 IPv4만 리스닝
연결 문자열의 localhost를 127.0.0.1로 바꾸는 것만으로도 대부분 해결된다. Docker를 쓴다면 포트 매핑(-p 27017:27017)을 빠뜨리지 않았는지 확인하자.
DB 연결 에러 관련해서 MySQL 연결 에러는 MySQL connection error 해결, Redis 연결 에러는 Redis connection refused 해결 글을 참고하면 된다.
댓글 없음:
댓글 쓰기