MongoDB는 전통적인 관계형 DB인 Mysql, Mssql, Oracle 등 과 달리, 비 관계형 DB이며, json과 같은 document 기반의 구조를 가진다.
관계형 DB에 비해 MongoDB는 데이터 저장 및 검색에 대해 덜 제한적이다.
이런 MongoDB를 더 편리하게 사용할 수 있는 Mongoose라는 npm 패키지를 소개하고자 한다.
MongoDB와 Mongoose 기본 개념(구조)
우선, 가장 작은 단위부터 보자.
MongoDB
Document
document는 mongoDB의 가장 작은 데이터 저장 단위이다.
이 document는 그냥 하나의 json object라고 보면 된다.
key:value를 저장하고 있는 text라는 의미이다.
Collection
Collection은 여러 Document의 모임이다.
이 collection의 이름은 일반적으로 그 collection이 가지고 있는 document의 단수형을 복수형으로 바꾼 것으로 한다.
비슷한(또는 같은) 형태의 document들을 모아둔 것이다.
물론 이런 관례를 무시하고 전혀 다른 형태의 document를 같은 collection에 쑤셔 넣을 수 있다.
하지만, 그건 좋은 생각이 아닐 것이다.
Database
Database는 여러 collection의 모임이다.
모임이라기보다는 소속되어 있는 장소라고 생각하는 게 편하다.
관리자는 여러 개의 database를 만들고 관리할 수 있다.
Mongoose
Model
mongoose의 model과 mongoDB의 document는,
이전 포스팅에서 말한 DOM과 HTML document의 관계성과 비슷하다.
mongoDB에서 document를 단순한 "text"이다.
이런 text를 구조화하고 생성 및 수정 등 DB에 접근하게 도와주는 여러 interface를 제공하는 것이,
바로 model이다.
model은 두 가지로 구성된다.
shema와 methods이다.
schema는 해당 document에 대한 구조의 definition(정의)이다.
정적으로 멤버들을 선언한다고 생각하면 된다.
methods는 schema에서 정의한 구조(key-value)대로 document를 create 하거나,
만든 document에 해당하는 collection에서 document를 검색하는 등의 DB에 access 하는 interface를 제공한다.
아래는 예제 코드이다.
const personSchema = new mongoose.Schema({ name: 'string', age: 'string' });
const Person = mongoose.model('Person', schema);
위 코드를 보면 한 가지 의문이 들 것이다.
"collection에 대한 언급이 없네?"
그렇다.
위에서는 어느 collection에 model로 생성한 document를 저장할지 정의하고 있지 않다.
그러면 어떻게 하는가?
mongoose는 자동으로 단수형 모델 이름의 복수형을 collection의 이름(lowercase 됨)으로 설정한다.
(물론 model의 세 번째 인자로 자신의 특정하여 collection이름을 설정할 수 있다.)
Mongoose automatically looks for the plural, lowercased version of your model name.
-mongoose 공식 문서-
Collection
mongoose에서 collection에 대해 건드릴 수 있는 건, 위에서 언급했듯이
model 호출할 때 세 번째 인자로 collection이름을 지정하는 것뿐이다.
Database
mongoose에서 database에 대해 건드릴 수 있는 건,
처음 connect를 호출할 때 database에 대한 url(또는 ip와 port)를 넘겨주는 것뿐이다.
mongoose
.connect(config.url, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true,
})
.then(() => {
logger.info("connected to MongoDB")
})
.catch((err) => {
logger.error("error connecting to MongoDB:", err.message)
})
JSON화
noteSchema.set('toJSON', {
transform: (document, returnedObject) => {
returnedObject.id = returnedObject._id.toString()
delete returnedObject._id
delete returnedObject.__v
}
})
CRUD
create : new Model({new properties}).save()
read : Model.find({}) or Model.findById(id)
update: Model.findByIdAndUpdate(id, {new properties}, {options})
delete: Model.findbyIdAndDelete(id)
느낀 점 및 더 말하고 싶은 점
역시 단순함을 추구하는 NoSQL이다. RDBMS에 비해 정말 Data Definition Langueage와 Data Management Lanuage를 작성하기 편해졌다.
또 두 collection 간의 관계도 object id를 저장하든지 해서 마음대로 서로가 서로를 참조(둘 다 Foreign Key를 가지도록) 만들어도 아무도(특히 DBMS가) 머라 안 한다. 중복 참조라고 혼내지 않는다는 말이다.
하지만, 만능은 아닌 게 Nosql자체가 join쿼리를 지원하지 않기 때문에 mongoose의 populate라는 method를 써서 두 collection을 join 하더라도 그 join 하는 도중에 일어나는 해당 collection의 update에 대해서는 join 된 결과에서는 보장하지 못한다.
보통 그냥 덜 보여도 reload 하면 되는 가벼운 일이나, read보다 write가 많을 때 사용한다고 한다.
참고한 사이트:(mongoose 공식 문서)
'개발 > node' 카테고리의 다른 글
import 시 확장자( .js ) 및 index 생략 (0) | 2022.11.22 |
---|---|
콜백(callback) 함수를 Promise로 바꾸기 (콜백함수로 await 쓰기) (0) | 2021.07.20 |
express에서 get, post 파라미터 가져오기 (0) | 2021.03.19 |
댓글