Mongoose 사용하기

MongoDB의 ODM인 mongoose를 express.js와 함께 사용해보았다.

폴더구조

1
2
3
4
5
6
7
8
9
10
11
12
13
back
├── models
│ └── user.js
├── router
│ └── user.js
├── node_modules
├── app.js
├── mongo.js
├── nodemon.json
├── package.json
├── package-lock.json
├── .env
└── .gitignore

model을 정의하기 위한 models폴더를 만들었다.
또한 루트 디렉터리에 MongoDB와 연결하기 위한 mongo.js파일을 만들었다.

설치

mongoose를 사용하기 위해 mongoose를 설치하였다.
또한 .env파일을 작성하기 위해 dotenv를 설치해주었다.

1
2
npm i mongoose
npm i dotenv

dotenv

내 데이터베이스의 주소인 MONGO_URI,
개발인지 배포인지 나타낼 NODE_ENV
그리고 express에서 사용할 포트넘버인 PORT를 작성해주었다.

.env

1
2
3
MONGO_URI=mongodb+srv://<username>:<password>@<clustername>.zdhw0.mongodb.net/<databasename>?retryWrites=true&w=majority
NODE_ENV="development"
PORT=8000

Mongoose를 express와 연결하기

MongoDB와 연결하는 함수를 모듈화 하였다.

./mongo.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const mongoose = require("mongoose"); //모듈을 불러옴
require("dotenv").config(); //.env를 사용하기 위해 불러옴

function dbConnect() {
if (process.env.NODE_ENV !== "production") {
mongoose.set("debug", true);
}
// production이 아닐 경우 debug가 true가 되도록 하였다.
mongoose.Promise = global.Promise;
mongoose
.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log("Successfully connected to mongodb!"))
.catch((e) => console.error(e));
}
// 연결 후 콘솔에 출력하도록 하였다.

module.exports = { dbConnect };
// app.js에서 사용할 수 있도록 하였다.

그 후 app.js에서 호출하여 데이터베이스와 연결 해주었다.

./app.js

1
2
3
4
5
6
7
...

const { dbConnect } = require("./mongo");
dbConnect();

...

Model과 Schema

Mongoose는 nosql인 MongoDB에 스키마를 도입하여 데이터를 DB에 넣기 전에 검사한다. 때문에 제약은 있지만 안정성을 더하였다.

다음과 같이 UserSchema를 작성하였다.

./models/user.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const mongoose = require("mongoose");

const UserSchema = new mongoose.Schema(
{
email: {
type: String,
required: true,
maxlength: 60,
},
username: {
type: String,
require: true,
maxlength: 20,
},
password: {
type: String,
require: true,
maxlength: 150,
},
},
{ timestamps: true }
);

module.exports = mongoose.models.User || mongoose.model("User", UserSchema);
// model함수를 호출하면 Schema가 등록된다.
// 어플리케이션에서 사용하기 위한 모델을 반환한다.

사용자 정의 메소드 정의하기

Mongoose에선 Schema혹은 모델의 인스턴스인 Document 객체 내부에 다양한 메서드를 정의하고 사용할 수 있다.

methods

mongoose는 스키마나 다큐먼트에 사용자 정의 메소드를 추가할 수 있다.

Schema 객체의 methods에 접근하여 함수를 추가해주었다.

내부의 this를 통해 Document에 접근할 수 있다.
때문에 화살표 함수를 사용하면 안 된다.

./models/user.js

1
2
3
4
5
UserSchema.methods.methodName = function () {
const document = this; //document 하나
...
return result;
};

호출시엔 새로운 Document를 만들어서 호출할 수 있다.

./models/user.js

1
2
const user=new User({...});
user.methodName();

statics

mongoose는 모델이나 쿼리에도 사용자 정의 메소드를 추가할 수 있다.

Schema 객체의 statics에 접근하여 함수를 추가해주었다.

내부의 this를 통해 Schema Collection에 접근할 수 있다.
마찬가지로 화살표 함수를 사용하면 안 된다.

나는 유효성 검사 메소드를 statics메서드로 정의해주었다.
이럴 경우 코드가 훨씬 깔끔해지는 것 같다.

1
2
3
4
5
UserSchema.statics.staticMethodName = function () {
const SchemaCollection = this; //Schema 전체
// ...
return result;
};

호출시엔 새로운 Document를 만들지 않고 User Colloection에 접근할 수 있다.

1
2
const user=new User({...});
user.staticMethodName();

느낀점

자질구레한 오타로 에를 좀 먹어서 다음엔 typescript도 같이 적용해보아야겠다.

ref

Mongoose(몽구스) 스키마(Schema)
Mongoose 스키마& 쿼리 기본
Mongoose 공식문서

body vs query vs params

express를 이용해 API를 호출하기 위한 세 가지 방식이 있다.

1. req.params

url이 https://pshdev1030.github.io/:id 일 경우
id를 req.params.id로 접근할 수 있다.

req.query

1
2
3
{
"id": "pshdev1030"
}

2. req.query

url이 https://pshdev1030.github.io/user?id=pshdev1030일 경우

req.query로 접근할 수 있다.

req.query

1
2
3
{
"id": "pshdev1030"
}

3. req.body

url을 이용하지 않고 요청에 json객체를 담아서 전송받아 사용한다.
req.body를 통해 접근할 수 있다.

in react

1
axios(endpoint, { id: "pshdev1030" });

req.body

1
2
3
{
"id": "pshdev1030"
}