MongoDB

박정훈·2022년 2월 28일
0

Backend

목록 보기
4/6

NoSQL (NOT ONLY SQL)

처리해야 하는 정보량의 급격한 증가로 탄생하게 된 NoSQL DB.
공부하며 느낀바로는 흔히 SQL문으로 다뤄지는 RDBMS보다 뭐랄까.. 틀이 딱 잡혀있는 느낌이 아니다.
또한 RDBMS는 안정성에 중점을 뒀다면 NoSQL은 확장성과 성능 최적화에 특화 되었다고 한다.
안정성에 중점을 뒀다보니 규칙이 빡세고, 특정 기능에 관해서 비효율적이다.
그에 반해 NoSQL은 특정 기능에서 강점을 가지는 식으로 부각되었다.
MongoDB는 그중에서도 NoSQL의 특징을 가지면서도 범용성적으로 부각된 것 같다.
즉, 고성능과 함께 안정화까지 갖춰졌다...!

분산 컴퓨팅

처리할 데이터량이 굉장히 많은 요즘엔 분산 컴퓨팅이 빈번하다. 현대적 DBMS는 분산 컴퓨팅을 하는것이 기본값이다.
MongoDB에서 지원하는 분산컴퓨팅으로는 복제샤딩이 있다.

복제

복제는 원본 서버가 망가져도 정상적인 서비스가 가능하도록 복사해 놓는 것이다. 안정성을 높여준다.

샤딩

읽기, 쓰기 성능 향상이 가능하다. 서버 여러대에 나누어서 저장함으로써 성능을 높인다.
하나의 서버 성능을 고성능으로 만드는 것보다 평범한 성능의 서버 여러대가 훨씬 저렴하게 먹힌다.

주의!

단일 인스턴스 DBMS에서 만약 쓰기 작업을 하다가 서버가 나가버린다면, mongoDB는 의도치 않게 중간 상태로 저장될 수도 있다.
기본적으로 안정성 레벨이 낮게 적용 되어있기 때문에 데이터가 유실될 가능성이 있는것이다. 물론 안정성을 높일 수 있다. 그리고 이는 곧 성능의 부하로 이어질 것이다.

JS 친화적인 DB

많은 인기를 얻게 된(?) 이유 중 하나일 것이다. SQL을 몰라도 되는! JS 기반의 DBMS를 사용해 주세여! 가 먹힌 것일까?

BSON

JSON과 매우 유사한 구조로 정보를 저장한다. RDBMS에서 스키마, 그러니까 테이블을 만들어 사용했다면, 그냥 Document로 대입 해 버리면 된다. (mongoose에서 스키마 나옴)

{
  name: 'malza',
  age: '100',
}

구조

RDBMS와 비교하자면
RDBMS에서의 DB - TABLE - ROW
MongoDM에서는 DB - COLLECTION - DOCUMENT

ObjectId

모든 Document에는 _id 필드가 있으며, 각 Document의 PK로 사용된다. 유일값이다.

...
MongoDB와 MongoDB Compass 설치를 끝내고 Compass에서 MongoDB와 연결까지 해봤다. collection을 만들었다 지웠다 해보고 find가지고 끄적거려봤다. 서버에서 지우니까 local에서도 지워지는거까지 확인.

Mongoose ODM

MongoDB의 Collection을 모델화 해서 쉽게 입맛대로 조리할 수 있게 해 준다.
이 친구는 MongoDB 관련 편한 기능을 제공하는데 간단하게 DB와의 연결상태를 관리하게 해 주며, 스키마 관리가 가능하다. 어?
분명 NoSQL의 장점이 스키마를 정의하지 않는것 이라고 했었다. 그럼에도?
미리 데이터 형식을 정의해 놓는다면 코드작성과 데이터양이 많아질수록 관리에 유용할 수 있다.
이러한 스키마정의를 CODE LEVEL에서 가능하게 해 준다.

사용해보자

스키마를 정의 -> 모델 만들기 -> 데이터 베이스 연결 -> 모델 사용

const { Schema } = require('mongoose')

const userSchema = new Schema({
  name: String,
  job: String
}, {
  timestamps: true, // 생성, 수정 시간을 자동으로 기록한다.
})

module.exports = userSchema;

모델 만들기

작성된 스키마를 mongoose에서 사용할 수 있게 모델로 만들어 준다.
모델의 이름을 User로 작성했고, 이 이름으로 모델을 호출할 수 있다.

const mongoose = require('mongoose');
const userSchema = require('./schemas/user');
exports.User = mongoose.model('User', userSchema);

데이터베이스에 연결

mongoose는 자동으로 연결을 관리해 준다. 개발자가 직접 연결 상태를 체크하지 않아도 모델을 사용할 때 연결상태를 확인해서 사용이 가능할 때 작업을 한다.

const mongoose = require('mongoose');
const { User } = require('./models');
mongoose.connect('내 데이터 베이스')

CREATE

create함수를 사용해서 Document를 생성할 수 있다.

const { User } = require('./models');
async function main() {
  const user1 = await User.create({
    name: "malza",
    job: "developer"
  });
}

FIND

find 관련 함수를 사용해 Document를 검색한다. query를 사용해 검색하거나 findByID는 ObjectID로 Document를 검색할 수 있다.

const { User } = require('./models');
async function main() {
  const malza = await User.find(query);
  const userById = await User.findById(id);
}

mongoose에서 쿼리 값으로 배열이 주어지면 자동으로 $in 쿼리를 수행한다.

User.find({name: ['malza', 'jiwoo']});
// { name: { $in: ['malza', 'jiwoo'] } }

UPDATE

update 관련 함수를 사용해 Document를 수정한다.
find~ 함수들은 검색된 Document를 업데이틑 반영해 반환해 준다.

async function main() {
  const updateUser = await User.updateOne(query, {
    ...
  });
  // updateMany등등
  const userById = await User.findByIdAndUpdate(id, {
    ...
  })
}

DELETE

async function main() {
  const deleteResult = await User.deleteOne(query);
  // deleteMany
  const oneUser = await User.findOneAndDelete(query);
}

Populate

MongoDB는 기본적으로 Join이 없다. 이와 비슷한 효과를 보기 위해서 aggregate 쿼리를 사용해야 하지만, Mongoose로는 populate를 사용하여 구현할 수 있다.

Document 안에 Document가 아닌, ObjectID를 가지고 reference하여 사용할 수 있는 방법을 제공한다.

const Post = new Schema({
  user: { // 단일객체로 ref 가능
    type: Schema.Types.ObjectId,
    ref: 'User' // 모델의 이름이다
  },
  comments: [{ // 배열로 ref 가능
    type: Schema.Types.ObjectId,
    ref: 'Comment', // 모델의 이름이다
  }],
});
====================================================
const post = await Post.find().populate(['user','comments']);
// post.user.name
// post.comments[0].content

Query 사용해보기

async function main() {
  const posts = await Post.find({
    // 쿼리 작성하기
    author: ['malza', 'judy', 'mike'], // $in 쿼리는 배열로 넘겨주면 자동으로 적용된다.
    likes: {
     $gt: 1, // 1보다 크고 
     $lte: 5, // 5보다 작거나 같게
    },
    $or: [ //category는 없거나 'IT' 인 것
        {category: { $exists: false } }, // 속성이 없는지를 확인한다.
        {category: 'IT' },
    ]
  });
  return posts;
}

connection

mongoose.connection.on('connected', () => {
}); // 연결 완료
mongoose.connection.on('disconnected', () => {
}); // 연결 끊김
mongoose.connection.on('reconnected', () => {
}); // 재연결 완료
mongoose.connection.on('reconnectFailed', () => {
}); // 재연결 시도 횟수 초과
profile
그냥 개인적으로 공부한 글들에 불과

0개의 댓글