유연한 데이터 저장소: MongoDB
MongoDB는 대표적인 NoSQL 데이터베이스입니다. 복잡한 표(Table) 형태가 아니라, 자바스크립트 객체(JSON)와 똑같이 생긴 도큐먼트(Document) 형태로 데이터를 저장합니다. 형식이 자유로워서 프론트엔드 개발자들이 적응하기 매우 쉽습니다.
RDBMS(MySQL) vs MongoDB 용어 비교
데이터를 다루는 방식은 비슷하지만 부르는 이름이 다릅니다. 이 차이를 이해하는 것이 MongoDB 학습의 첫걸음입니다.
| 개념 |
MySQL (RDBMS) |
MongoDB (NoSQL) |
| 데이터 1건 |
Row (행/레코드) |
Document (도큐먼트) |
| 데이터 집합(그룹) |
Table (테이블) |
Collection (컬렉션) |
| 고유 식별자(기본키) |
Primary Key (id) |
_id (자동 생성되는 난수 문자열) |
Mongoose 모듈: 너무 자유로운 건 위험하니까!
MongoDB는 너무 자유로워서 숫자 자리에 문자를 넣거나 필수 항목을 빼먹고 저장해도 오류가 나지 않습니다. 이런 데이터 오염을 막기 위해 Mongoose (몽구스)라는 ODM 라이브러리를 사용합니다.
// Mongoose를 이용해 "User" 데이터의 설계도(Schema) 작성
const userSchema = new mongoose.Schema({
username: { type: String, required: true }, // 문자열, 필수
age: { type: Number, min: 0 }, // 숫자, 0 이상
createdAt: { type: Date, default: Date.now } // 기본값: 현재 시간
});
⚠️ 주의: 스키마(Schema)와 모델(Model)의 차이
스키마(Schema)는 단순히 데이터의 형태를 정의한 '설계도'일 뿐입니다. 이 설계도를 가지고 실제 DB에 데이터를 넣고(save), 찾고(find) 지우려면 mongoose.model('User', userSchema) 를 통해 조종석 격인 모델(Model) 객체로 변환해야 합니다.
Mongoose 스키마 검증(Validation) 시뮬레이션
아무 데이터나 다 받아주는 MongoDB의 자유로움을 통제하기 위해, Mongoose 스키마(Schema)가 불량 데이터를 어떻게 막아내는지 확인해 보세요.
const mongoose = require('mongoose');
// 1. 유저 스키마(규칙) 정의
const userSchema = new mongoose.Schema({
name: { type: String, required: true }, // 필수 문자열
age: { type: Number, min: 0 } // 0 이상의 숫자
});
// 2. 모델 생성
const User = mongoose.model('User', userSchema);
async function testValidation() {
console.log('[테스트 1] 정상 데이터 저장 시도: { name: "Minstudio", age: 30 }');
try {
const user1 = new User({ name: 'Minstudio', age: 30 });
await user1.validate(); // DB 저장 전 Mongoose 검증만 수행
console.log('> ✅ 검증 통과! DB에 정상 저장됩니다.\n');
} catch (err) { console.log(err.message); }
console.log('[테스트 2] 타입 오류 시도: { name: "User", age: "서른살" }');
try {
const user2 = new User({ name: 'User', age: '서른살' });
await user2.validate();
} catch (err) {
console.log('> 🚨 검증 실패 (ValidationError): "age" 필드에는 Number(숫자)만 가능합니다!\n');
}
console.log('[테스트 3] 필수값 누락 시도: { age: 25 }');
try {
const user3 = new User({ age: 25 });
await user3.validate();
} catch (err) {
console.log('> 🚨 검증 실패 (ValidationError): "name" 필드는 required: true 이므로 생략 불가!\n');
}
}
testValidation();
$ node validation_test.js
[테스트 1] 정상 데이터 저장 시도: { name: "Minstudio", age: 30 }
> ✅ 검증 통과! DB에 정상 저장됩니다.
[테스트 2] 타입 오류 시도: { name: "User", age: "서른살" }
> 🚨 검증 실패 (ValidationError): "age" 필드에는 Number(숫자)만 가능합니다!
[테스트 3] 필수값 누락 시도: { age: 25 }
> 🚨 검증 실패 (ValidationError): "name" 필드는 required: true 이므로 생략 불가!