Join us Sept 17 at .local NYC! Use code WEB50 to save 50% on tickets. Learn more >
MongoDB Event
Docs Menu
Docs Home
/ / /
Node.js 드라이버
/

튜토리얼: Mongoose 시작하기

Mongoose 는 MongoDB 용 ODM(객체 데이터 모델링) 라이브러리입니다. Mongoose 사용하여 데이터 모델링, 스키마 시행, 모델 유효성 검사 및 일반적인 데이터 조작을 지원할 수 있습니다. MongoDB 향후 데이터베이스를 변경하고 업데이트 수 있는 유연한 데이터 모델을 제공하므로 엄격한 스키마가 없습니다. 그러나 Mongoose 처음부터 반강제 스키마 적용하므로 스키마 와 모델을 정의해야 합니다.

스키마 컬렉션 문서의 구조를 정의합니다. Mongoose 스키마 MongoDB 컬렉션 에 직접 매핑됩니다.

다음 예시 blog이라는 새 스키마를 만듭니다.

const blog = new Schema({
title: String,
slug: String,
published: Boolean,
author: String,
content: String,
tags: [String],
comments: [{
user: String,
content: String,
votes: Number
}]
}, {
timestamps: true
});

스키마 만들 때 각 필드 와 해당 데이터 유형을 정의해야 합니다. 허용되는 유형은 다음과 같습니다.

  • 문자열

  • 번호

  • 날짜

  • Buffer

  • 부울

  • 혼합

  • ObjectId

  • 배열

  • Int32

  • Decimal128

  • Double

  • Map

모델은 스키마 가져와 컬렉션 의 각 문서 에 적용 . 모델은 생성, 읽기, 업데이트, 삭제 (CRUD ) 작업과 같은 모든 문서 상호 작용을 담당합니다.

모델에 전달하는 첫 번째 인수는 컬렉션 이름의 단수형입니다. Mongoose 이 값을 자동으로 복수형으로 변경하고 소문자로 변환한 다음 이를 데이터베이스 컬렉션 이름으로 사용합니다.

다음 예시 blog 스키마 사용하는 Blog 이라는 모델을 선언하는 방법을 보여 줍니다.

const Blog = mongoose.model('Blog', blog);

앞의 예시 에서 Blog 은 MongoDB 에서 blogs 컬렉션 으로 변환됩니다.

이 튜토리얼에서는 다음 작업을 수행합니다.

  • Mongoose 사용할 수 있는 환경 설정

  • MongoDB에 연결

  • Mongoose 스키마 및 모델 만들기

  • 데이터 삽입, 업데이트, 찾기 및 삭제

  • 문서 필드 프로젝트

  • 데이터 유효성 검사

  • 여러 스키마 및 미들웨어 사용

1

이 튜토리얼을 시작하기 전에 다음 구성 요소가 준비되어 있는지 확인하십시오.

  • 클러스터 구성된 MongoDB Atlas 계정. 지침을 보려면 Atlas 시작하기 가이드 참조하세요.

  • Node.js v16.20.1 또는 그 이후 버전.

2

이 튜토리얼에서는 nodemon을 사용하여 로컬에서 코드를 실행 . 터미널에서 다음 명령을 실행하여 프로젝트 초기화하고 필요한 종속성을 설치합니다.

mkdir mongodb-mongoose
cd mongodb-mongoose
npm init -y
npm i mongoose
npm i -D nodemon

선호하는 코드 편집기에서 프로젝트 엽니다. 이 튜토리얼에서는 CommonJS 대신 ES 모듈을 사용합니다. ES 모듈을 사용하려면 module 유형을 추가해야 합니다. package.json 파일 로 고 (Go) 다음 코드를 추가합니다.

...
"scripts": {
"dev": "nodemon index.js"
},
"type": "module",
...

다음 명령을 실행 하여 nodemon 으로 애플리케이션 시작합니다.

npm run dev

참고

nodemon을 사용하면 파일 저장할 때마다 코드가 실행됩니다.

3

프로젝트 의 루트 수준에서 index.js 파일 만들고 파일 맨 위에 다음 코드를 추가합니다.

import mongoose from 'mongoose';
mongoose.connect("<connection string>")

<connection string> 자리 표시자를 MongoDB Atlas 연결 문자열 로 바꿉니다. 연결 문자열 찾는 방법에 대한 자세한 내용은 Atlas 설명서에서 Connect to Your Cluster(클러스터에 연결하기) 튜토리얼을 참조하세요.

4

MongoDB 에서 데이터 추가 및 업데이트를 시작하기 전에 스키마 와 모델을 만들어야 합니다.

Mongoose 사용하면 필요한 각 스키마 에 대한 스키마 모델 파일 생성할 수 있습니다. 먼저 모든 스키마 파일을 넣을 model 폴더를 만든 다음 Blog.js 첫 번째 스키마 파일 만듭니다. 이 파일 열고 다음 코드를 추가합니다.

import mongoose from 'mongoose';
const { Schema, model } = mongoose;
const blogSchema = new Schema({
title: String,
slug: String,
published: Boolean,
author: String,
content: String,
tags: [String],
comments: [{
user: String,
content: String,
votes: Number
}]
}, {
timestamps: true
});
const Blog = model('Blog', blogSchema);
export default Blog;

이 스키마 자동으로 업데이트되는 스키마 에 mongoose-managed createdAtupdatedAt 필드를 추가하는 timestamps 옵션을 활성화합니다. 자세한 내용은 Mongoose 문서의 타임스탬프 페이지를 참조하세요.

5

이제 첫 번째 모델과 스키마 설정하다 완료되었으며 데이터베이스 에 데이터 삽입을 시작할 수 있습니다. 다음 섹션에서는 Mongoose 사용하여 CRUD 작업을 수행하는 방법을 보여줍니다.

index.js (으)로 고 (Go) 파일 맨 위에 다음 가져오기 성명서 추가합니다.

import Blog from './model/Blog.js';

연결 문자열 포함된 줄 아래에 다음 코드를 추가합니다.

// Creates a new blog post and inserts it into database
const article = await Blog.create({
title: 'Awesome Post!',
slug: 'awesome-post',
published: true,
content: 'This is the best post ever',
tags: ['featured', 'announcement'],
});
console.log('Created article:', article);

앞의 코드는 Mongoose create() 메서드를 사용하여 블로그 기사를 나타내는 객체 인스턴스화한 다음 데이터베이스 에 저장합니다. 반환된 문서 _id를 포함하여 콘솔에 기록됩니다. 이후 단계에서 사용할 수 있도록 이 _id 를 기록해 둡니다.

데이터를 업데이트 하려면 Mongoose 사용하여 로컬 객체 직접 편집할 수 있습니다. 그런 다음 save() 메서드를 사용하여 데이터베이스 에 업데이트 쓰기 (write) 수 있습니다.

다음 코드를 추가하여 이전 섹션에서 삽입한 아티클을 업데이트 .

// Updates the title of the article
article.title = "The Most Awesomest Post!!";
await article.save();
console.log('Updated Article:', article);
Updated Article: {
title: 'The Most Awesomest Post!!',
slug: 'awesome-post',
published: true,
content: 'This is the best post ever',
tags: [ 'featured', 'announcement' ],
_id: new ObjectId('...'),
comments: [],
__v: 0
}

특정 문서 찾으려면 Mongoose findById() 메서드를 사용하여 문서 의 _id을(를) 지정하여 문서를 쿼리 할 수 있습니다.

index.js 파일 에 다음 코드를 추가하여 _id로 특정 기사를 찾습니다.

// Finds the article by its ID. Replace <object id> with the objectId of the article.
const articleFound = await Blog.findById("<object id>").exec();
console.log('Found Article by ID:', articleFound);
Found Article by ID: {
_id: new ObjectId('68261c9dae39e390341c367c'),
title: 'The Most Awesomest Post!!',
slug: 'awesome-post',
published: true,
content: 'This is the best post ever',
tags: [ 'featured', 'announcement' ],
comments: [],
__v: 0
}

참고

기본값 으로 Mongoose 쿼리는 JavaScript Promise의 일부 속성을 가진 객체인 thenable을 반환합니다. 쿼리 에 exec() 메서드를 추가하여 실제 JavaScript Promise를 받을 수 있습니다. Mongoose 에서 프로미스 작업에 대해 자세히 학습하려면 Mongoose 문서의 프로미스 가이드 를 참조하세요.

Mongoose 사용하여 필요한 필드만 프로젝트 할 수 있습니다. 다음 코드는 title, slugcontent 필드만 프로젝트 하도록 지정합니다.

index.js 파일 에 다음 코드를 추가하고 <object id> 자리 표시자를 이전에 삽입한 문서 의 ObjectId 값으로 바꿉니다.

// Finds the article by its ID and projects only the title, slug, and content fields.
// Replace <object id> with the objectId of the article.
const articleProject = await Blog.findById("<object id>", "title slug content").exec();
console.log('Projected Article:', articleProject);
Projected Article: {
_id: new ObjectId('...'),
title: 'The Most Awesomest Post!!',
slug: 'awesome-post',
content: 'This is the best post ever'
}

Mongoose deleteOne()deleteMany() 메서드를 사용하여 컬렉션 에서 데이터를 삭제 . 삭제 하려는 문서 의 필드 지정하고 해당 필드 선택한 메서드에 전달할 수 있습니다.

데이터베이스 에서 하나의 아티클을 삭제 하려면 인덱스.js 파일 에 다음 코드를 추가하세요.

// Deletes one article with the slug "awesome-post".
const blogOne = await Blog.deleteOne({ slug: "awesome-post" });
console.log('Deleted One Blog:', blogOne);
Deleted One Blog: { acknowledged: true, deletedCount: 1 }

여러 아티클을 삭제 하려면 다음 코드를 추가하면 됩니다.

// Deletes all articles with the slug "awesome-post".
const blogMany = await Blog.deleteMany({ slug: "awesome-post" });
console.log('Deleted Many Blogs:', blogMany);
Deleted Many Blogs: { acknowledged: true, deletedCount: 4 }
6

이전 단계에서 삽입된 아티클 스키마 author, dates 또는 comments 필드가 포함되어 있더라도 포함되지 않습니다. 이는 문서 의 구조를 정의했지만 필수 필드를 정의하지 않았기 때문입니다. 필수로 정의되지 않은 필드 생략할 수 있습니다.

Mongoose 에서 필드 에 유효성 검사 포함하는 경우 객체 해당 값으로 전달해야 합니다.

참고

유효성 검사기는 create()save() 메서드에서 자동으로 실행 . runValidators 옵션을 true로 설정하여 update()updateOne() 와 같은 업데이트 메서드에서 실행 지정할 수 있습니다. 유효성 검사기에 대한 자세한 내용은 Mongoose 설명서의 유효성 검사 페이지를 참조하세요.

Mongoose 에서는 여러 가지 유효성 검사 방법을 사용할 수 있습니다. 예시 를 들어, 요구하려는 모든 필드에 대해 required 를 true로 설정하다 수 있습니다. 유형과 서식의 유효성을 검사할 수도 있습니다. 다음 코드에서 slug 필드 4minLength 이 있는 string 로 정의됩니다. 즉, 4 자 미만으로 slug 를 제공하면 ValidationError이(가) 됩니다.

데이터 유효성 검사 추가하고 이러한 요구 사항을 정의하려면 다음 예시 와 같이 Blog.js 에서 스키마 업데이트 .

const blogSchema = new Schema({
title: {
type: String,
required: true,
},
slug: {
type: String,
required: true,
minLength: 4,
},
published: {
type: Boolean,
default: false,
},
author: {
type: String,
required: true,
},
content: String,
tags: [String],
comments: [{
user: String,
content: String,
votes: Number
}]
}, {
timestamps: true
});

이 유효성 검사 추가하면 애플리케이션 충돌합니다. 새로운 유효성 검사 검사 요구 사항을 충족하려면 index.js 파일 의 create() 호출에 author 필드 추가합니다.

// Creates a new blog post and inserts it into database
const article = await Blog.create({
title: 'Awesome Post!',
slug: 'awesome-post',
published: true,
author: 'A.B. Cee',
content: 'This is the best post ever',
tags: ['featured', 'announcement'],
});

Mongoose 와 함께 스키마를 사용하는 경우 value: Stringvalue: {type: String} 와 동일합니다.

자세한 내용은 Mongoose 설명서의 유효성 검사 페이지를 참조하세요.

7

다음으로, 다른 스키마 만들고 블로그 스키마 에 중첩하여 author 필드 에 더 많은 복잡성을 추가할 수 있습니다.

model 폴더에서 User.js라는 새 파일 만듭니다. 이 파일 에 다음 코드를 추가합니다.

import mongoose from 'mongoose';
const {Schema, model} = mongoose;
const userSchema = new Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
minLength: 10,
required: true,
lowercase: true
},
});
const User = model('User', userSchema);
export default User;

새 사용자 모델을 사용하여 블로그 스키마 에서 author 필드 정의하려면 Blog.js 파일 다음 변경 사항으로 업데이트 .

  • Mongoose 라이브러리에서 추출한 속성 목록에 SchemaTypes 를 추가합니다.

  • author 필드 typeSchemaTypes.ObjectId 로 변경하고 'User' 모델에 참조(ref)를 추가합니다.

다음 코드는 이러한 업데이트를 보여줍니다.

const { Schema, SchemaTypes, model } = mongoose;
... // Inside Schema block:
author: {
type: SchemaTypes.ObjectId,
ref: 'User',
required: true,
},
...

blogSchema 정의를 변경하여 comment.user 필드 에 대해 동일한 User 모델을 재사용할 수 있습니다.

... // Inside Schema block:
comments: [{
user: {
type: SchemaTypes.ObjectId,
ref: 'User',
required: true,
},
...

애플리케이션 에서 새 사용자 모델을 사용하려면 index.js 파일 로 고 (Go) . 사용자 모델을 가져오려면 파일 맨 위에 다음 코드를 추가합니다.

import User from './model/User.js';

블로그 스키마 에 필드 유효성 검사 추가했기 때문에 블로그를 삽입, 업데이트 및 삭제 하고 프로젝트 에 필드를 지정하는 이전 코드는 유효성 검사 통과하지 못하고 애플리케이션 에 오류가 발생합니다.

다음 create() 호출을 추가하여 새 사용자를 만듭니다.

// Create a new user
const user = await User.create({
name: 'Jess Garica',
email: 'jgarcia@email.com',
});

다음 코드에 표시된 대로 기존 create() 호출을 다음 코드로 업데이트하여 새 사용자를 작성자로 사용하는 새 아티클을 만듭니다.

// Creates a new blog post that references the user as the author
const articleAuthor = await Blog.create({
title: 'Awesome Post!',
slug: 'Awesome-Post',
author: user._id,
content: 'This is the best post ever',
tags: ['featured', 'announcement'],
});
console.log('Article with Author:', articleAuthor);
Article with Author: {
title: 'Awesome Post!',
slug: 'awesome-post',
published: false,
author: new ObjectId('...'),
content: 'This is the best post ever',
tags: [ 'featured', 'announcement' ],
_id: new ObjectId('...'),
createdAt: 2025-05-15T18:05:23.780Z,
comments: [],
__v: 0
}

앞의 코드는 MongoDB database 에 users 컬렉션 blogs 컬렉션 과 함께 추가합니다. 이 코드는 필수 author 필드 추가하고 해당 값을 user._id로 설정합니다.

nameemail 필드 값을 기사의 author 필드 에 추가하려면 블로그 쿼리 에 Mongoose populate() 메서드를 추가하면 됩니다. populate() 메서드는 user._id가 참조하는 사용자 문서 에 대해 두 번째 쿼리 수행합니다.

다음 코드를 index.js 에 추가하여 이 데이터를 채웁니다.

// Populates the author field with user data
const articlePopulate = await Blog.findOne({ title: "Awesome Post!" }).populate("author");
console.log('Article Populated:', articlePopulate);
Article Populated: {
_id: new ObjectId('...'),
title: 'Awesome Post!',
slug: 'awesome-post',
published: false,
author: {
_id: new ObjectId('...'),
name: 'Jess Garica',
email: 'jgarcia@email.com',
__v: 0
},
content: 'This is the best post ever',
tags: [ 'featured', 'announcement' ],
createdAt: 2025-05-15T18:04:28.590Z,
comments: [],
__v: 0
}

자세한 내용은 Document.population() 을 참조하세요. Mongoose API 문서의 페이지입니다.

8

Mongoose 에서 미들웨어는 스키마 수준에서 비동기 함수를 실행하기 전이나 실행하는 동안 실행 함수입니다.

미들웨어의 한 가지 예시 저장하거나 업데이트하기 전에 User 인스턴스 의 email 필드 의 유효성을 검사하는 함수입니다.

이 예시 validator 패키지 사용합니다. 다음 명령을 실행 하여 validator 패키지 설치할 수 있습니다.

npm install validator

이 미들웨어 함수를 추가하려면 User.js 파일 의 userSchema 선언에 다음 코드를 추가합니다.

import validator from 'validator';
userSchema.pre('save', function (next) {
const user = this;
// Normalize email
if (user.email) {
user.email = user.email.trim().toLowerCase();
}
// Validate email format
if (!validator.isEmail(user.email)) {
return next(new Error('Invalid email format'));
}
next();
});

이 함수의 효과를 확인하려면 index.js 파일 의 user.email 필드 잘못된 이메일 주소 로 수정합니다.

const user = await User.create({
name: 'Jess Garica',
email: 'jgarciaemail.com',
});
Error: Invalid email format

이메일 주소 수정하면 오류가 발생하지 않는 것을 확인할 수 있습니다.

pre() 미들웨어 함수 외에도 Mongoose post() 미들웨어 함수도 제공합니다. 미들웨어에 대한 자세한 내용은 Mongoose 설명서의 미들웨어 페이지를 참조하세요.

이제 Mongoose 사용하여 MongoDB 컬렉션 에서 CRUD 작업을 수행하는 샘플 프로젝트 생겼습니다. 여기에서 이 프로젝트 를 기반으로 더 복잡한 쿼리 또는 문서 유효성 검사 빌드 하도록 선택할 수 있습니다. 다음 섹션에는 애플리케이션 에서 사용할 수 있는 Mongoose 기능의 몇 가지 예가 포함되어 있습니다.

사용자 지정 설정자는 데이터가 저장될 때 데이터를 수정하며, 유효성 검사기와 유사하게 구현할 수 있습니다. Mongoose 다음과 같은 사용자 지정 설정자를 제공합니다.

  • lowercase

  • uppercase

  • trim

다음 예시 blog.slug 필드 의 문자를 소문자로 표시합니다.

const blogSchema = new Schema({
...
slug: {
type: String,
required: true,
minLength: 4,
lowercase: true,
},
...
});

자세한 내용은 Mongoose API 설명서의 SchemaStringOptions 페이지를 참조하세요.

Mongoose 에는 일반 MongoDB 메서드에서 추상화된 여러 헬퍼 메서드가 포함되어 있습니다. 이 섹션에서는 이러한 메서드 중 일부의 예를 찾을 수 있습니다. 이러한 메서드는 이 튜토리얼에서 구체적으로 사용되지 않지만 Mongoose 시작할 때 참고하는 데 유용합니다.

exists() 메서드는 null 또는 제공된 쿼리 와 일치하는 첫 번째 문서 반환합니다. 다음은 author 필드 기준으로 아티클을 일치시키는 예시 입니다.

const blog = await Blog.exists({ author: 'Jess Garcia' });
console.log(blog);

자세한 내용은 Model.exists() 섹션을 API Mongoose .

where() 메서드를 사용하면 복잡한 쿼리를 연결하고 빌드 수 있습니다.

다음은 일반 쿼리 객체 와 함께 findOne() 를 사용하고 where() 메서드로 이에 상응하는 쿼리 사용하여 찾기 작업을 수행하는 예시 입니다.

const blogFind = await Blog.findOne({ author: "Jess Garcia" });
console.log(blogFind);
const blogWhere = await Blog.findOne().where("author").equals("Jess Garcia");
console.log(blogWhere);

이 구현 에서 where() 구현 findOne() 로 시작하여 Mongoose 이를 findOne() 쿼리 로 처리하도록 지시합니다. 이는 where() 을 단독으로 사용하는 경우(Blog.where(...)) Mongoose 이를 암시적으로 find() 작업으로 처리하기 때문에 중요합니다.

일반적으로 where() 메서드는 동적 쿼리 작성 또는 여러 비교기가 포함된 복잡한 쿼리에 사용되거나 이 메서드를 사용하면 가독성이 향상됩니다. where() 메서드를 사용하는 것과 일반 객체 쿼리 사용하는 것 사이에는 성능 차이가 없습니다.

where() 메서드를 사용할 때 프로젝션 포함하려면 다음 예시 와 같이 쿼리 뒤에 select() 메서드를 연결합니다.

const blog = await Blog.findOne().where("author").equals("Jess Garcia").select("title author");
console.log(blog);

자세한 내용은 Mongoose API 문서의 다음 섹션을 참조하세요.

MongoDB 와 함께 Mongoose 사용하는 방법에 대해 자세히 학습하려면 Mongoose 설명서를 참조하세요.

지원 찾거나 MongoDB Community 에 기여하려면 MongoDB 개발자 커뮤니티 페이지를 참조하세요.

돌아가기

타사 통합

이 페이지의 내용