Mongoose
- Node.js와 MongoDB를 위한 ODM(Object Data Mapping) 라이브러리
- Javascript Object와 MongoDB의 데이터를 Mapping하여 호환성을 만들어내고, 간편한 CRUD를 가능
npm i mongoose
// db/database.js
import { config } from '../config.js';
import Mongoose from 'mongoose';
export async function connectDB(){
return Mongoose.connect(config.db.host);
}
export function useVirtualId(schema){
schema.virtual('id').get(function(){
return this._id.toString();
});
schema.set('toJSN', {virtuals:true});
schema.set('toObject', {virtuals:true});
}
let db;
export function getUsers(){
return db.collection('users'); //데이터를 넣을 때 users객체에 넣겠다
}
export function getTweets(){
return db.collection('tweets');
}
// app.js
// app.js
import express from "express";
import morgan from "morgan";
import tweetsRouter from './router/tweets.js'
import authRouter from './router/auth.js'
import { config } from "./config.js";
// import { sequelize } from "./db/database.js";
import { connectDB } from "./db/database.js";
const app = express();
app.use(express.json()); // json로 연결
app.use(morgan("dev"));
//tweetsRouter 미들웨어 등록
app.use('/tweets', tweetsRouter);
//authsRouter 미들웨어 등록
app.use('/auth', authRouter);
app.use((req, res, next) => {
res.sendStatus(404);
});
// DB 연결 테스트!
// db.getConnection().then(Connection => console.log(Connection));
// sequelize.sync().then(() => {
// app.listen(config.host.port);
// });
connectDB().then((db) => {
console.log('몽구스를 사용하여 몽고디비에 접속 성공!');
app.listen(config.host.port);
}).catch(console.error);
// app.listen(config.host.port);
// data/auth.js
// data/auth.js
import Mongoose from 'mongoose';
import { useVirtualId } from '../db/database.js';
const userSchema = new Mongoose.Schema({
username: {type: String, require: true},
name: {type: String, require: true},
email: {type: String, require: true},
password: {type: String, require: true},
url: String
});
useVirtualId(userSchema);
const User = Mongoose.model('User', userSchema) // 컬랙션생성
// // 아이디(username) 중복 검사
export async function findByUsername(username){
return User.findOne({username});
}
// // id 중복 검사
export async function findById(id){
return User.findById(id);
}
export async function createUser(user){
return new User(user).save().then((data) => data.id);
}
// data/tweet.js
import * as authRepository from './auth.js';
const tweetSchema = new Mongoose.Schema({
userid: {type: String, require: true},
username: {type: String, require: true},
name: {type: String, require: true},
text: {type: String, require: true},
url: String
}, {timestamps: true})
useVirtualId(tweetSchema);
const Tweet = Mongoose.model('Tweet', tweetSchema);
// 모든 트윗을 리턴
export async function getAll() {
return Tweet.find().sort({createAt: -1});
}
// 해당 아이디에 대한 트윗을 리턴
export async function getAllByUsername(username){
return Tweet.find({username}).sort({createAt: -1});
}
// 글번호에 대한 트윗을 리턴
export async function getById(id){
return Tweet.findById(id);
}
// 트윗을 작성
export async function create(text, userId){
return authRepository.findById(userId).then((user) => new Tweet({ text, userId, name: user.name, username: user.username, url: user.url}).save());
}
// 트윗을 변경
export async function update(id, text){
return Tweet.findByIdAndUpdate(id, {text}, {returnDocument: "after"});
}
// 트윗을 삭제
export async function remove(id){
return Tweet.findByIdAndDelete(id);
}
🤍
ChatGPT를 통해 공부한 오늘의 내용 -
✔ mongoose란?
Mongoose는 MongoDB를 Node.js 애플리케이션에서 사용하기 쉽도록 도와주는 ODM(Object Data Modeling) 라이브러리입니다. MongoDB는 NoSQL 데이터베이스로, JSON 스타일의 문서를 저장하고 조회할 수 있는 데이터베이스입니다.
Mongoose는 MongoDB와 상호 작용하기 위한 편리한 방법을 제공합니다. 주요 기능은 다음과 같습니다:
- 스키마 기반 모델링: Mongoose는 MongoDB 문서의 구조를 정의하기 위해 스키마를 사용합니다. 이를 통해 데이터 모델링이 간단하고 일관성 있게 됩니다.
- 데이터 유효성 검사: Mongoose는 스키마를 정의할 때 필드 유형 및 제약 조건을 지정할 수 있습니다. 이를 통해 데이터의 유효성을 보장하고 잘못된 데이터가 데이터베이스에 저장되지 않도록 할 수 있습니다.
- 쿼리 빌더: Mongoose는 MongoDB 쿼리를 구축하기 위한 강력한 API를 제공합니다. 이를 사용하여 데이터를 쉽게 검색, 수정, 삭제할 수 있습니다.
- 미들웨어 지원: Mongoose는 데이터베이스 작업 전후에 실행되는 미들웨어 훅을 제공합니다. 이를 사용하여 데이터의 변환, 유효성 검사, 로깅 등과 같은 작업을 수행할 수 있습니다.
- 인덱스 및 성능 최적화: Mongoose는 인덱스 생성과 같은 MongoDB의 성능 최적화 기능을 활용할 수 있습니다.
이러한 기능들을 통해 Mongoose는 Node.js 애플리케이션에서 MongoDB를 사용하는 프로세스를 단순화하고 개발 생산성을 향상시킵니다.
✔ Mongoose에서 데이터 유효성 검사
Mongoose에서 데이터 유효성 검사를 수행하는 방법은 주로 다음과 같습니다.
- 스키마 정의: 먼저, Mongoose 스키마를 사용하여 데이터 모델의 구조를 정의합니다. 스키마는 각 필드의 유형을 정의하고, 필드의 유효성을 검사하기 위한 규칙을 설정합니다.
2. 필수 필드 및 유형 정의: required: true를 사용하여 필드가 반드시 존재해야 함을 지정할 수 있습니다. 각 필드의 유형도 스키마를 통해 정의할 수 있습니다.
3. 고유한 필드 설정: unique: true를 사용하여 필드가 고유해야 함을 지정할 수 있습니다. 이를 통해 중복된 데이터를 방지할 수 있습니다.
4. 사용자 정의 유효성 검사: 필드에 대해 추가적인 사용자 정의 유효성 검사를 수행할 수 있습니다. validate 속성을 사용하여 함수를 정의하고 해당 함수에서 사용자 지정 유효성 검사를 수행할 수 있습니다.
이렇게 정의된 스키마를 통해 Mongoose는 데이터가 스키마와 일치하는지 자동으로 검사합니다. 데이터가 스키마와 일치하지 않는 경우, Mongoose는 해당 데이터를 MongoDB에 저장하지 않고 오류를 반환합니다. 이를 통해 데이터의 유효성을 보장하고 잘못된 데이터가 데이터베이스에 저장되는 것을 방지할 수 있습니다.
✔ Mongoose에서 미들웨어
Mongoose에서의 "미들웨어"란 데이터베이스 작업이 실행되기 전이나 후에 실행되는 함수입니다. 이러한 함수를 사용하여 데이터베이스 작업의 전처리나 후처리를 수행할 수 있습니다. Mongoose에서 미들웨어는 주로 스키마에 바인딩되며, 해당 스키마와 관련된 데이터베이스 작업 전후에 실행됩니다.
Mongoose에서 미들웨어를 사용하는 주요 목적은 다음과 같습니다.
- 전처리: 데이터베이스 작업이 실행되기 전에 입력 데이터를 가공하거나 유효성을 검사하는 등의 작업을 수행할 수 있습니다. 예를 들어, 입력 데이터를 해싱하거나 암호화하여 저장할 수 있습니다.
- 후처리: 데이터베이스 작업이 실행된 후에는 결과를 가공하거나 로깅하는 등의 작업을 수행할 수 있습니다. 예를 들어, 데이터가 업데이트된 후에 특정 로그를 생성하거나 관리자에게 알림을 보낼 수 있습니다.
미들웨어는 Mongoose의 여러 이벤트를 기반으로 실행됩니다. 가장 일반적으로 사용되는 이벤트는 다음과 같습니다.
- validate: 데이터가 스키마의 유효성 검사를 통과하기 전에 실행됩니다.
- save: 문서가 데이터베이스에 저장되기 전에 실행됩니다.
- remove: 문서가 데이터베이스에서 제거되기 전에 실행됩니다.
- init: 문서가 Mongoose 모델로 초기화될 때 실행됩니다.
- findOneAndUpdate, findOneAndRemove 등의 특정 쿼리 메서드 호출 시 발생하는 이벤트 등이 있습니다.
이러한 미들웨어 함수는 Mongoose 스키마에 pre() 또는 post() 메서드를 사용하여 등록됩니다. pre() 메서드는 데이터베이스 작업이 실행되기 전에 실행되는 미들웨어를 등록하고, post() 메서드는 데이터베이스 작업이 실행된 후에 실행되는 미들웨어를 등록합니다.
✔ useVirtualId 란?
useVirtualId는 Mongoose의 옵션 중 하나입니다. Mongoose는 MongoDB와 상호 작용하는 Node.js 애플리케이션을 작성할 때 사용되는 ODM(Object Data Modeling) 라이브러리입니다. useVirtualId 옵션은 Mongoose 스키마에 가상 필드를 생성하여 MongoDB 문서의 ID를 가상으로 가져오는 기능을 제공합니다.
일반적으로 MongoDB의 문서는 _id 필드를 가지고 있으며, 이 필드는 고유한 식별자로 사용됩니다. Mongoose에서는 이를 id 필드로 사용하고자 할 때 useVirtualId 옵션을 사용할 수 있습니다.
예를 들어, 다음과 같이 Mongoose 스키마를 정의할 수 있습니다.
이렇게 설정하면 User 모델에서 id 필드를 가상으로 가져올 수 있습니다. 가상 필드는 실제로 데이터베이스에 저장되지 않지만, Mongoose에서는 사용자가 기본 ID 대신에 가상 ID를 사용할 수 있습니다.
✔ export async function getAll() { return Tweet.find().sort({createAt: -1}); } 여기서 createAt: -1?
이 코드는 Node.js에서 Mongoose를 사용하여 MongoDB에서 데이터를 가져오는 함수를 정의합니다. 이 함수는 getAll이라는 이름으로 내보내지고, MongoDB의 Tweet 컬렉션에서 모든 문서를 가져오는 작업을 수행합니다. 그리고 createAt 필드를 기준으로 내림차순으로 정렬합니다.
여기서 각 부분의 의미는 다음과 같습니다:
- export async function getAll() { ... }: 이 코드는 ES6의 모듈 시스템을 사용하여 getAll 함수를 내보내는 것을 의미합니다. 이 함수는 외부에서 임포트하여 사용할 수 있습니다.
- return Tweet.find().sort({createAt: -1});: 이 부분은 Mongoose의 Tweet 모델을 사용하여 MongoDB의 Tweet 컬렉션에서 모든 문서를 찾고, createAt 필드를 기준으로 내림차순으로 정렬합니다. 그리고 이 작업의 결과를 반환합니다. 즉, 이 함수를 호출하면 MongoDB에서 모든 트윗을 가져와 최신 트윗부터 정렬된 상태로 반환합니다.
따라서 이 함수는 주어진 MongoDB 데이터베이스에서 모든 트윗을 가져와 정렬된 상태로 반환하는 역할을 합니다.
✔ export async function update(id, text){ return Tweet.findByIdAndUpdate(id, {text}, {returnDocument: "after"}); } 여기서 after?
{ returnDocument: "after" } 옵션은 MongoDB의 findByIdAndUpdate() 메서드에서 사용되는 옵션 중 하나입니다. 이 옵션은 업데이트된 문서를 반환할 때 어떤 버전을 반환할지를 결정합니다.
- returnDocument: "after": 이 옵션을 사용하면 업데이트가 적용된 이후의 문서를 반환합니다. 즉, 업데이트 작업 후의 최신 버전의 문서를 반환합니다.
예를 들어, findByIdAndUpdate() 메서드를 사용하여 문서를 업데이트하고 해당 옵션을 "after"로 설정하면 업데이트 이후의 문서가 반환됩니다. 이를 사용하면 업데이트된 데이터에 대한 확신을 가지고 작업할 수 있습니다.
따라서 returnDocument: "after" 옵션은 업데이트 작업 이후의 문서를 반환함으로써 데이터의 일관성을 보장하고 프로그래머에게 신뢰성 있는 데이터를 제공합니다.