개발

[Mongoose] Connections과 srv 레코드

Crmal 2023. 3. 27. 14:35

Connections

mongoose를 연결하는 기본적인 구조는 아래와 같다.

// 로컬 서버에 접속할 경우
mongoose.connect('mongodb://localhost:27017/myapp');

// 클라우드 서버에 접속할 때
mongoose.connect('mongodb://username:password@host:port/database?options...');

Operation Buffering

mongoose는 기술적으로 우리가 app을 실행했을 때 바로 mongodb와 연결이 되어 우리가 앱을 작동할 수 있게 한다.

mongoose.connect('mongodb://localhost:27017/myapp');
const MyModel = mongoose.model('Test', new Schema({name: String}));

MyModel.findOne(function(error, result) {/* ... */});

// 연결되지 않으면 에러가 발생하지 않고, 연결되면 에러가 발생한다. 
setTimeout(function() {
    mongoose.connect('mongodb://localhost:27017/myapp');
}, 60000);

 

 

mongoose에서 내부적으로 모델 함수를 호출하기 때문에 편리하지만 연결하지 않고 모델 함수를 사용하면 우리는 에러를 알 수 없는 단점이 존재한다.

 

버퍼링은 우리가 autoCreate를 사용하면 컬렉션을 생성하는 동안 발생한다. 만약 이 경우에도 버퍼링을 작동하지 않게 하려면 createCollection()을 사용하거나 autoCreate 옵션을 변경하면 된다.

const schema = new Schema({
    name: String
}, {
    capped: {size: 1024},
    bufferCommands: false,
    autoCreate: false
});

const Model = mongoose.model('Test', schema);
await Model.createCollection();

Error Handling

연결과정에서 발생하는 오류 유형에는 다음과 같이 존재한다.

  • 초기에 연결할 때 연결에 실패한다면 error 를 호출하고 mongoose.connect()가 거부된다. 이때, 자동적으로 재연결되지 않으니 다시 시도해야 한다.
  • 초기 연결이 끝난 이후 다시 연결을 시도할 때 에러가 발생한다.

이 경우 .catch()나 try/catch로 해결할 수 있다.

mongoose.connect('mongodb://localhost:27017/test').
    catch(error => handleError(error));

or

try {
    awiat mongoose.connect('mongodb://localhost:27017/test');
} catch (error) {
    handleError(error);
}

 

연결 이후에 다시 연결 오류가 발생할 경우에는 아래와 같이 error를 호출할 수 있다.

mongoose.connection.on('error', err => {
    logError(err);
})

Options

connect 함수에 options 오브젝트를 이용해 MongoDB에 여러 정보를 전달 할 수 있다.

기본 형태

mongoose.connect(uri, options);

예시

cosnt options = {
    autoIndex: false,
    maxPoolSize: 10,
    serverSelectionTimeoutMS: 5000,
    socketTimeoutMS: 45000,
    family: 4
};
mongoose.connect(uri, options);

Callback

connect 함수에 promise로 콜백 파라미터를 사용할 수 있다.

mongoose.connect(uri, options, function(error){
    초기 에러를 체크하고 콜백을 위한 파라미터가 없다.
});

mongoose.connect(uri, options).then(
    () => { 사용할 준비가 된 경우 }
    err => { 초기 에러가 발생한 경우 }
);

keepAlive (서버 유지)

애플리케이션을 서버에 올리고 작동시킬 때 ms 단위로 서버 환경을 체크하게 되는데 시간이 지나면 서버가 꺼지기 때문에 계속 서버를 유지하기 위해서는 아래와 같이 해야 한다.

mongoose.connect(uri, {keepAlive: true, keepAliveInitialDelay: 300000});

Replica Set Connections (서버 복사)

기본적으로 여러 서버에 복사해 운영하는 법

mongoose.connect('mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]' [, options]);

mongoose.connect('mongodb://user:pw@host1.com:27017,host2.com:27017,host3.com:27017/testdb');

하나의 서버 복사본과 연결할 때

mongoose.connect('mongodb://host1:port1/?replicaSet=rsName');

Server Selection (서버 탐색)

Mongoose가 uri를 통해 서버를 탐색하는 동안 서버에 연결이 되지 않는 경우 에러가 발생한다.

MongoTimeoutError: Server selection timed out after 30000 ms

따라서, serverSelectTimeoutMS로 일정 시간 이후에 서버 연결이 되지 않으면 에러를 발생시킬 수 있다.

const mongoose = require('mongoose');

const uri = 'mongodb+srv://username:badpw@cluster0-OMITTED.mongodb.net/' + 'test?retryWrites=true&w=majority';

mongoose.connect(uri, {
  serverSelectionTimeoutMS: 5000
}).catch(err => console.log(err.reason));

Multi connections

Multi-connections를 이용하는 이유는 2가지 이다.

  • 하나는 우리가 여러 DB를 사용할 경우
  • 다른 하나는 DB 탐색 시 동시 들어온 요청을 빠르게 처리하고 싶은 경우 (slow trains 이라고 함)

기본 형태

const conn = mongoose.createConnection('mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]', options);

여기서 봐야하는 것은 module.exports를 진행할 때 Schema 형태로 내보내야 한다는 것이다.

const userSchema = new Schema({ name: String, email: String });

module.exports = userSchema;
const UserModel = conn.model('User', userSchema);

예시) 스키마 패턴을 외부로 꺼내 모델과 연결 시키는 경우

// connections/fast.js
const mongoose = require('mongoose');

const conn = mongoose.createConnection(process.env.MONGODB_URI);
comm.model('User', require('../schemas/user'));

module.exports = conn;

// connections/slow.js
const mongoose = require('mongoose');

const conn = mongoose.createConnection(process.env.MONGODB_URO);
conn.model('User', require('../schemas/user'));
conn.model('PageView', require('../schemas/pageView'));

model.exports = conn;

예시) 의존성 주입 혹은 Inversion of Control(IOC) 패턴으로 연결 시키는 경우

const mongoose = require('mongoose');

module.exports = function connectionFactory() {
    const conn = mongoose.createConnection(process.env.MONGODB_URI);

    conn.model('User', require('../schemas/user'));
    conn.model('Pageview', require('../schemas/pageView'));

    return conn;
};

Connection Pools

우리가 연결할 때 mongoose.connect와 mongoose.createConnection 를 사용하는데 이때 기본적인 최대 사이즈는 100으로 설정되어 있다. 그래서 이 최대 pool 사이즈를 수정하기 위해서는 options을 활용하면 된다.

mongoose.createConnection(uri, { maxPoolSize: 10 });

const uri = 'mongodb://localhost:27017/test?maxPoolSize=10';
mongoose.createConnection(uri);

https://velog.io/@guri_coding/mongoose-공부하기-3-Connections-파헤치기

[mongoose 공부하기 [3] - Connections 파헤치기

mongoose의 핵심인 Connection을 공부하고 정리했습니다.

velog.io](https://velog.io/@guri_coding/mongoose-공부하기-3-Connections-파헤치기)

위의 내용을 가져왔습니다.


SRC 레코드

위를 공부하면서 mongodb uri에 src가 붙거나 안붙거나 무슨 차이일지 궁금해졌습니다.

스택오버플로우의 답변에 의하면 다음과 같습니다.

 

MongoDB 3.6에는 DNS 레코드, 특히 SRVTXT 레코드를 사용하여 지정되는 시드 목록 개념이 도입되었습니다.
연결 시 클라이언트가 적어도 하나의 복제본 세트 구성원을 지정해야 한다는
MongoDB와 함께 복제본 세트를 사용하는 것을 기억할 것입니다(여러 개를 지정할 수도 있음).
이렇게 하면 클라이언트가 지정한 노드 중 하나를 사용할 수 없는 경우에도 클라이언트가 복제 세트에 연결할 수 있습니다.

 

SRV레코드란 무엇인가

 

서비스 레코드 ( SRV 레코드 ) 는 지정된 서비스에 대한 서버의 위치(예: 호스트 이름 및 포트 번호)를
정의하는 도메인 이름 시스템 의 데이터 사양입니다 .

 

SRV는 우리가 db와 커넥팅할때 입력해주는 도메인주소의 일정 규격을 의미 합니다 SRV를 붙이는 이유는 해당 규격을 명시 해주는것 입니다.

다음과 같은 내용이 담겨 있습니다.