https://github.com/wanted-wecode-subjects/aimmo-subject-teamB
MongoDB는 NoSQL 중 가장 많이 쓰이는 데이터베이스입니다.
NoSQL은 Not Only SQL의 약자로 RDBMS와는 달리 고정된 스키마나 복잡한 JOIN이 존재하지 않습니다.
또한 key-value 쌍으로 데이터를 표현합니다.
{
"_id": ObjectId("5099803df3f4948bd2f98391"),
"username": "velopert",
"name": { first: "M.J.", last: "Kim" }
}
NoSQL을 RDBMS와 비교하여 볼 때 다음과 같이 정리할 수 있습니다.
RDBMS | NoSQL |
---|---|
Database | Database |
Table | Collection |
Column | Field, Key |
Row | Document |
_id는 12bytes의 hexadecimal 값으로 각 document의 유일성을 제공합니다.
Document는 동적 schema를 갖고 있습니다.
즉, 같은 Collection의 다른 Document 사이에 다른 key를 가질 수 있습니다.
다음과 같은 요구사항이 있다고 가정합니다.
이를 RDBMS로 디자인하면 다음과 같이 3개의 테이블을 생성해야 합니다.
반면 NoSQL로 디자인하면 다음과 같이 Document를 작성할 수 있습니다.
즉, 하나의 Document에 세 데이터를 넣을 수 있습니다.
{
"_id":"POST_ID",
"title":"POST_TITLE",
"content":"POST_CONTENT",
"username":"POST_WRITER",
"tags":[
TAG1,
TAG2,
TAG3
],
"time":"POST_TIME",
"comments":[
{
"username":"COMMENT_WRITER",
"mesage":"COMMENT_MESSAGE",
"time":"COMMENT_TIME"
},
{
"username":"COMMENT_WRITER",
"mesage":"COMMENT_MESSAGE",
"time":"COMMENT_TIME"
}
]
}
MongoDB self ref을 사용하여 대댓글을 구현하였습니다.
댓글의 schema는 다음과 같습니다.
Comment {
content: string;
author: string;
depth: number;
parentCommentId: string;
comments: Comment[];
created_at: Date;
updated_at: Date;
postId: string;
}
댓글의 경우 depth가 0이 되고, parentCommentId에는 빈 값이 들어갑니다.
그리고 대댓글은 depth가 1이 되며, parentCommentId에는 부모 댓글의 _id가 들어갑니다.
이 과정에서 comments의 comment가 자기 참조를 할 수 있도록 @Prop 데코레이터를 @Prop({type: [{type: mongoose.Schema.Types.ObjectId, ref: 'Comment'}]})
와 같이 적용하였습니다.
댓글이 존재하는 상황에서 대댓글이 등록되면 다음과 같이 조회가 됩니다.
{
"_id": "618176d0bf01ef0f96c163bb",
"postId": "postId",
"updated_at": "2021-11-02T17:35:12.347Z",
"created_at": "2021-11-02T17:35:12.347Z",
"comments": [
"618176fabf01ef0f96c163c2",
],
"depth": 0,
"author": "testuser",
"content": "댓글",
"__v": 3
}
NoSQL을 처음 써보게 되어 초기에 진행이 더뎠습니다.
또한, 초기에 ORM으로 사용하려던 TypeORM이 MongoDB와는 호환이 잘 안되는 이슈가 있어 진행에 어려움을 겪었습니다.
예를 들어, 데이터 조회시 typeorm mongodb cannot read property 'prototype' of undefined
같은 에러가 발생하는 경우가 있습니다. 이는 버전에 대한 문제로 인해 발생하는 이슈이며, 이 때문에 mongoose를 대체로 사용하였습니다.
(관련 글: TypeORM + MongoDB 적용 및 사용하지 않게 된 이유)
NoSQL로 스키마를 작성하고, 기능을 구현하였으나, NoSQL스럽게 스키마를 작성하고 코드를 구현하였는지도 약간 의문스럽습니다.
예를 들어, comment의 postId 같은 필드가 foreign key 처럼 사용된 것 같아 꺼림칙합니다.
한가지 다행이라고 생각되는 점은 이후에 NoSQL을 사용할 때 오늘만큼을 헤매지 않을 것 같다는 점입니다.
추후 제가 만들고자 하는 애플리케이션의 DB로 NoSQL을 사용한다거나 관련된 내용을 마주했을 때 좀 더 가벼운 마음으로 개발을 진행할 수 있을 것 같습니다.