- MongoDB에서 스키마를 사용하는 방법은 여러가지가 있지만, 가장 일반적인 방법으로는 Mongoose(Node.js)를 사용하는 것이다.
- Mongoose는 MongoDB와 Node.js 사이의 Object Document Mapping(ODM) 라이브러리로, MongoDB 데이터베이스에서 데이터를 조작할 때 스키마를 적용할 수 있는 기능을 제공한다.
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const contactSchema = new Schema({ name: { type: String, required: true }, email: { type: String, required: true }, phone: { type: String, required: true, unique: true }, }); const Contact = mongoose.model('Contact', contactSchema); module.exports = Contact;
- 위의 예제는 Mongoose를 사용하여 주소록의 연락처를 나타내는 Contact 모델을 정의하는 것이다.
contactSchema
에서는 이름, 이메일, 전화번호 필드가 필수적으로 포함되어야 하며, 전화번호 필드는 유일해야 함을 정의한다.
MongoDB에서, 엔티티는 데이터베이스에 저장된 개체, 즉 문서를 나타내는 것이다. 이 문서는 특정 속성과 값을 갖고 있으며, 데이터베이스 컬렉션의 멤버이기도 하다.
데이터베이스 컬렉션에서 멤버는 그 컬렉션 내의 개별 문서를 의미한다. 각 문서는 엔티티의 개별 인스턴스를 나타내며, 컬렉션 내의 모든 문서는 그 컬렉션의 멤버를 구성한다.
Instance는 객체지향 프로그래밍에서 클래스의 실제 예시, 특정 개체, 구체적인 객체를 의미한다. 클래스의 정의를 따르는 어떤 개체를 말한다. 예를 들어, 개발자가 정의한 "Person" 클래스의 인스턴스는 "John", "Jane" 등의 개인이 될 수 있다.
MongoDB에서 One-to-One 관계는 두 개의 엔티티 사이의 관계를 나타내는 것으로, 각 엔티티는 하나의 연관된 엔티티만을 가질 수 있다는 것을 뜻한다. 다른 말로, 한 컬렉션에 있는 한 개의 문서는 다른 컬렉션에 있는 한 개의 문서와만 관련될 수 있다는 것이다.
// User Collection
{
"_id": ObjectId("5f3e6..."),
"name": "John Doe",
"email": "johndoe@example.com",
"address_id": ObjectId("5f3e7...")
}
// Address Collection
{
"_id": ObjectId("5f3e7..."),
"street": "123 Main St",
"city": "San Francisco",
"state": "CA",
"zip": "94111"
}
MongoDB에서 One-to-Many 관계란, 한 개의 문서가 다른 컬렉션의 여러 문서와 관계를 갖는 것을 의미한다.
즉, 한 컬렉션의 한 개의 문서가 다른 컬렉션의 여러 개의 문서와 관계를 갖는 것을 말한다.
const User = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
posts: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}]
});
const Post = new mongoose.Schema({
title: {
type: String,
required: true
},
body: {
type: String,
required: true
},
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
});
MongoDB에서의 Many-to-Many 관계란, 각 엔티티가 여러 개의 연관 엔티티를 가질 수 있는 관계를 의미한다. 다른 말로 하자면, 한 컬렉션의 문서는 다른 컬렉션의 여러 문서와 관련이 있을 수 있고, 반대도 마찬가지이다.
// "Student" collection document
{
"_id": ObjectId("5f56fde9ccb3f6d1e2fec70a"),
"name": "John Doe",
"enrollments": [
ObjectId("5f56fde9ccb3f6d1e2fec70b"),
ObjectId("5f56fde9ccb3f6d1e2fec70c")
]
}
// "Course" collection document
{
"_id": ObjectId("5f56fde9ccb3f6d1e2fec70b"),
"name": "Computer Science 101",
"students": [
ObjectId("5f56fde9ccb3f6d1e2fec70a"),
ObjectId("5f56fde9ccb3f6d1e2fec70d")
]
}
"_id"
필드를 참조하여, 두 컬렉션 간의 Many-to-Many 관계를 설정한다.데이터베이스에서 데이터 간의 연결 관계를 정의하고 구현하는 것을 말한다.
데이터의 정제와 정규화, 효율적인 데이터 관리를 위해 필요하다.
어떤 방식을 사용할지는 데이터의 종류, 용도, 사용자의 필요에 따라 결정되어야 한다.
데이터 접근 패턴: 관련 문서의 데이터를 자주 접근해야 할 경우, Embedded 관계 모델링 방식을 사용하는 것이 효율적일 수 있다.
반대로, 관련 문서를 별도로 업데이트해야 할 경우 Referenced 관계 모델링 방식을 고려해야 할 수 있다.
데이터 크기: 관련 문서가 작은 경우, 이들을 Embedded 문서로 저장하는 것이 편리하다.
관련 문서가 큰 경우, 이들을 별도의 문서로 저장하고 Referenced 관계를 사용하여 이들을 연결하는 것이 더 좋다.
일관성: Embedded 관계 모델링은 단일 문서 내에서 트랜잭션 일관성을 유지할 수 있지만, Referenced 관계 모델링은 수동적인 일관성 관리가 필요하다.
성능: Embedded 관계를 사용한 쿼리는 보통 빠르지만, 문서 크기가 커지면 느려질 수 있다. Referenced 관계는 쿼리에서 느릴 수 있지만, 문서 크기가 커지도 성능이 저하되지 않는다.
관계가 있는 두 문서를 하나의 문서에 임베딩하여 관계를 표현하는 방식
Embedded는 관계가 있는 두 문서의 데이터를 하나의 문서에 저장하여 관계를 표현
{
_id: ObjectId("5f60a2c6401ca095f5befa5a"),
name: "John Doe",
address: {
street: "123 Main St",
city: "San Francisco",
state: "CA",
zip: 94109
},
email: "john.doe@example.com"
}
관련된 데이터를 하나의 문서에 모두 포함시켜 저장하는 방식이다.
위의 예시에서 "John Doe" 사용자의 주소 정보는 "John Doe" 문서 안에 포함되어 저장되고 있다.
Embedded 데이터 구조는 다음과 같은 데이터에 적합하다.
Embedded Documents 방식의 장점:
Embedded Documents 방식의 단점:
관련된 데이터를 다른 문서에 참조하는 방식(관계가 있는 두 문서의 ObjectID를 가지고 관계를 표현)
참조 문서에서 관계가 있는 문서의 ObjectID를 저장하여 관계를 표현할 수 있으며, 관련 문서에 대한 정보를 가지고 있는 문서를 참조할 수 있다.
// Embedded방식을 Referenced방식으로 변경
// user document
{
_id: ObjectId("5f60a2c6401ca095f5befa5a"),
name: "John Doe",
address_id: ObjectId("5f60a2c6401ca095f5befa5b"),
email: "john.doe@example.com"
}
// address document
{
_id: ObjectId("5f60a2c6401ca095f5befa5b"),
street: "123 Main St",
city: "San Francisco",
state: "CA",
zip: 94109
}
관련된 데이터를 분리하여 다른 문서에 저장하는 방식이다.
위의 예시에서 "John Doe" 사용자의 주소 정보는 별도의 "Address" 문서에 저장되고 "John Doe" 문서에는 "Address" 문서의 ObjectId 값이 참조되고 있다.
Referenced 방식은 관계형 데이터베이스의 개념에 기반한 데이터 구조에 적합
Referenced Documents 방식의 장점:
Referenced Documents 방식의 단점:
정규화(normalization)-데이터베이스 구조를 최소한의 중복으로 만들어 데이터의 일관성과 안정성을 높이는 것을 목적.
- 정규화의 장점:
- 데이터 중복을 줄이고 불일치한 데이터를 제거한다.
- 데이터의 정질과 정확성을 향상시킨다.
- 데이터베이스의 확장성과 유지 관리성을 지원한다.
- 정규화의 단점:
- 데이터베이스 구조와 쿼리의 복잡성이 증가한다.
- 여러 조인이 필요하여 쿼리 성능이 느려진다.
- 데이터 삽입, 업데이트, 삭제가 어려워진다.
비정규화(denormalization)-정규화에서 제거된 데이터를 다시 테이블에 포함시켜 읽기 성능을 향상시키는 것을 목적.
- 비정규화의 장점:
- 조인의 수를 줄여 쿼리 성능을 향상시킨다.
- 데이터 조회를 더욱 간단하고 효율적으로 만든다.
- 데이터베이스 구조의 복잡성을 줄인다.
- 비정규화의 단점:
- 데이터 중복이 증가하고 불일치하는 데이터의 위험성이 증가한다.
- 데이터 정확성과 일관성이 감소한다.
- 데이터를 업데이트하고 유지하는 것이 더욱 어렵다.
따라서 정규화와 비정규화의 밸런스를 잘 잡아야 하며, 적절한 경우에는 정규화를, 읽기 성능이 중요한 경우에는 비정규화를 활용하는 것이 좋다.