MongoDB를 사용하다 보면 가끔 마주치는 골치 아픈 에러 중 하나가 바로 ‘connection timeout calling ismaster‘ 입니다. 이 에러는 특히 프로덕션 환경에서 갑자기 나타나면 당황스러울 수 있는데, 실제로 많은 개발자들이 이 문제로 고생하고 있습니다. 오늘은 이 에러가 왜 발생하는지, 그리고 어떻게 해결할 수 있는지 자세히 알아보겠습니다.

 

1. ismaster 에러란 무엇인가?

MongoDB의 ismaster 명령어(현재는 hello 명령어로 대체됨)는 클라이언트가 서버의 상태와 역할을 확인하기 위해 사용하는 핵심 명령어입니다. 이 명령어가 timeout되면 다음과 같은 에러 메시지를 보게 됩니다:

No suitable servers found (`serverSelectionTryOnce` set): 
[connection timeout calling ismaster on 'mongodb-server:27017']

이 에러는 MongoDB 드라이버가 서버와의 연결을 시도할 때, 서버 선택 과정에서 적절한 서버를 찾지 못하거나 연결이 시간 초과될 때 발생합니다.

ismaster에서 hello로의 변화

MongoDB 5.0부터 ismaster 명령어는 hello 명령어로 공식적으로 대체되었습니다. 하지만 여전히 많은 드라이버와 애플리케이션에서 ismaster 에러 메시지를 보게 되는 이유는 하위 호환성 때문입니다.

 

 

2. 에러 발생의 주요 원인들

네트워크 연결 문제

가장 흔한 원인 중 하나는 네트워크 연결 문제입니다. 방화벽, 보안 그룹, 또는 네트워크 설정이 MongoDB 포트(기본 27017)에 대한 접근을 차단하고 있을 수 있습니다.

MongoDB Atlas IP 화이트리스트 문제

MongoDB Atlas를 사용하는 경우, IP 주소가 화이트리스트에 등록되지 않았거나 동적 IP 환경에서 IP가 변경되었을 때 이 에러가 발생할 수 있습니다.

서버 과부하 및 연결 풀 고갈

서버가 과부하 상태이거나 연결 풀이 고갈된 상태에서는 새로운 연결 요청에 대한 응답이 지연되어 timeout이 발생할 수 있습니다.

인증 및 권한 문제

잘못된 인증 정보나 권한 부족으로 인해 연결이 거부되면서 timeout 에러로 나타날 수 있습니다.

 

 

3. 단계별 확인 방법

기본 연결 테스트

먼저 MongoDB 서버에 대한 기본적인 연결을 테스트해보세요:

# 포트 연결 테스트
telnet mongodb-server 27017

# 또는 nc 명령어 사용
nc -zv mongodb-server 27017

MongoDB Shell을 통한 연결 확인

mongosh "mongodb://username:password@mongodb-server:27017/database"

네트워크 진단

# DNS 해상도 확인
nslookup mongodb-server

# ping 테스트
ping mongodb-server

# 경로 추적
traceroute mongodb-server

 

 

4. ‘connection timeout calling ismaster’ 에러 해결 방법들

타임아웃 설정 조정

가장 직접적인 해결책은 MongoDB 클라이언트의 타임아웃 설정을 조정하는 것입니다:

// Node.js 예시
const { MongoClient } = require('mongodb');

const client = new MongoClient('mongodb://localhost:27017', {
  serverSelectionTimeoutMS: 30000, // 30초
  connectTimeoutMS: 20000,         // 20초
  socketTimeoutMS: 20000,          // 20초
  maxPoolSize: 10
});
// PHP 예시
$client = new MongoDB\Client(
    'mongodb://localhost:27017',
    [
        'serverSelectionTimeoutMS' => 30000,
        'connectTimeoutMS' => 20000,
        'socketTimeoutMS' => 20000
    ]
);

MongoDB Atlas 네트워크 접근 설정

MongoDB Atlas를 사용하는 경우:

  1. Atlas 대시보드에서 “Network Access” 메뉴로 이동
  2. “Add IP Address” 클릭
  3. 현재 IP 주소를 확인하고 추가 (whatismyipaddress.com에서 확인 가능)
  4. 개발 환경에서는 임시로 “Allow access from anywhere (0.0.0.0/0)” 설정 고려

연결 문자열 최적화

연결 문자열에 적절한 옵션을 추가하여 안정성을 높일 수 있습니다:

mongodb+srv://username:password@cluster.mongodb.net/database?
retryWrites=true&
w=majority&
serverSelectionTimeoutMS=30000&
connectTimeoutMS=20000&
socketTimeoutMS=20000

MongoDB 서버 설정 확인

/etc/mongod.conf 파일에서 bindIp 설정을 확인하세요:

net:
  port: 27017
  bindIp: 0.0.0.0  # 모든 IP에서 접근 허용 (보안 주의)

설정 변경 후 MongoDB 재시작:

sudo systemctl restart mongod

 

 

5. 프로덕션 환경 최적화 방법

연결 풀 관리

적절한 연결 풀 크기 설정으로 성능을 최적화할 수 있습니다:

const client = new MongoClient(uri, {
  maxPoolSize: 50,        // 최대 연결 수
  minPoolSize: 5,         // 최소 연결 수
  maxIdleTimeMS: 30000,   // 유휴 연결 타임아웃
  serverSelectionTimeoutMS: 5000,
  socketTimeoutMS: 45000,
});

모니터링 및 알림 설정

MongoDB의 상태를 지속적으로 모니터링하는 것이 중요합니다:

// 연결 상태 모니터링 예시
client.on('serverOpening', (event) => {
  console.log('새 서버 연결:', event);
});

client.on('serverClosed', (event) => {
  console.log('서버 연결 종료:', event);
});

client.on('error', (error) => {
  console.error('MongoDB 연결 에러:', error);
});

재연결 로직 구현

애플리케이션에 재연결 로직을 구현하여 일시적인 네트워크 문제에 대응할 수 있습니다:

async function connectWithRetry() {
  const maxRetries = 5;
  let retries = 0;
  
  while (retries < maxRetries) {
    try {
      await client.connect();
      console.log('MongoDB 연결 성공');
      return;
    } catch (error) {
      retries++;
      console.log(`연결 실패. 재시도 ${retries}/${maxRetries}`);
      
      if (retries === maxRetries) {
        throw error;
      }
      
      // 지수 백오프
      await new Promise(resolve => 
        setTimeout(resolve, Math.pow(2, retries) * 1000)
      );
    }
  }
}

 

 

6. 실제 상황별 해결방법

사례 1: PHP Laravel 환경에서의 간헐적 에러

문제: Laravel 애플리케이션에서 브라우저 접근 시에만 에러 발생, CLI에서는 정상 작동

해결책:

// config/database.php에서 MongoDB 연결 설정 조정
'mongodb' => [
    'driver' => 'mongodb',
    'host' => env('DB_HOST', '127.0.0.1'),
    'port' => env('DB_PORT', 27017),
    'database' => env('DB_DATABASE'),
    'username' => env('DB_USERNAME'),
    'password' => env('DB_PASSWORD'),
    'options' => [
        'serverSelectionTimeoutMS' => 30000,
        'connectTimeoutMS' => 20000,
        'socketTimeoutMS' => 20000,
    ],
],

사례 2: Docker 환경에서의 연결 문제

문제: Docker 컨테이너 간 MongoDB 연결 시 timeout 발생

해결책:

# docker-compose.yml
version: '3.8'
services:
  mongodb:
    image: mongo:5.0
    ports:
      - "27017:27017"
    networks:
      - app-network
  
  app:
    build: .
    depends_on:
      - mongodb
    environment:
      - MONGODB_URI=mongodb://mongodb:27017/mydb
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

사례 3: AWS 환경에서의 보안 그룹 문제

문제: EC2에서 MongoDB Atlas 연결 시 timeout

해결책:

  1. AWS 보안 그룹에서 아웃바운드 규칙 확인
  2. MongoDB Atlas 네트워크 접근 목록에 EC2 IP 추가
  3. VPC 엔드포인트 사용 고려

 

 

7. 에러 발생을 예방하려면?

정기적인 연결 테스트

// 헬스체크 함수 구현
async function healthCheck() {
  try {
    await client.admin().ping();
    return { status: 'healthy', timestamp: new Date() };
  } catch (error) {
    return { status: 'unhealthy', error: error.message, timestamp: new Date() };
  }
}

// 정기적 헬스체크 실행
setInterval(healthCheck, 30000); // 30초마다 체크

로그 모니터링

MongoDB 로그를 정기적으로 모니터링하여 문제의 징후를 조기에 발견하세요:

# MongoDB 로그 실시간 모니터링
tail -f /var/log/mongodb/mongod.log | grep -i "timeout\|error\|slow"

성능 메트릭 추적

중요한 메트릭들을 추적하여 문제를 예방하세요:

메트릭 목표값 모니터링 방법
연결 수 최대값의 80% 이하 db.serverStatus().connections
응답 시간 100ms 이하 애플리케이션 로그
CPU 사용률 80% 이하 시스템 모니터링
메모리 사용률 85% 이하 시스템 모니터링

 

MongoDB의 ‘connection timeout calling ismaster’ 에러는 다양한 원인으로 발생할 수 있지만, 체계적인 접근을 통해 해결할 수 있습니다. 무엇보다 중요한 것은 에러가 발생했을 때 당황하지 말고 단계별로 원인을 찾아가는 것입니다. 적절한 타임아웃 설정, 네트워크 구성 확인, 그리고 지속적인 모니터링을 통해 안정적인 MongoDB 환경을 구축할 수 있습니다. 이런 에러들이 발생하면 처음에는 막막하게 느껴질 수 있지만, 원인을 하나씩 체크해보면 생각보다 해결이 어렵지 않은 경우가 많습니다. 특히 네트워크 관련 문제가 대부분이므로, 연결성부터 차근차근 확인해보시길 권합니다. 🙂

 

댓글 남기기