프로젝트/할일목록(TODO) 앱

할일목록(TODO) 앱 3 - Mongoose 로 데이터 모델 설계 및 구현하기

syleemomo 2021. 10. 5. 19:25
728x90

https://mongoosejs.com/

 

Mongoose ODM v7.4.2

Let's face it, writing MongoDB validation, casting and business logic boilerplate is a drag. That's why we wrote Mongoose. const mongoose = require('mongoose'); mongoose.connect('mongodb://127.0.0.1:27017/test'); const Cat = mongoose.model('Cat', { name:

mongoosejs.com

 

* 데이터 모델 설계 - Todo

필드명 설명 데이터 타입 비고
author 할일을 작성한 작성자 ObjectId  ref: 'User'
title 할일에 대한 제목 String trim: true 
description 할일에 대한 구체적인 설명 String trim: true 
isDone 할일의 완료 상태  Boolean default: false 
createdAt 할일의 생성날짜  Date default: Date.now
lastModifiedAt 할일의 수정날짜  Date default: Date.now
finishedAt 할일의 완료날짜  Date default: Date.now

NoSQL은 언제든지 스키마를 변경하고 유연하게 데이터를 저장할 수 있기 때문에 우선은 간단하게 설계를 진행하도록 한다. 추후 필요하면 필드를 추가할 예정이다.

 

* 데이터 모델 구현 - Todo

const mongoose = require('mongoose')

const { Schema } = mongoose
const { Types: { ObjectId } } = Schema

const todoSchema = new Schema({ // 스키마 정의
  author: {
    type: ObjectId, 
    required: true,
    ref: 'User'
  },
  title: {
    type: String,
    required: true,
    trim: true
  },
  description: {
    type: String,
    trim: true,
  },
  isDone: {
    type: Boolean,
    default: false,
  },
  createdAt: {
    type: Date,
    default: Date.now,
  },
  lastModifiedAt: {
    type: Date,
    default: Date.now,
  },
  finishedAt: {
    type: Date,
    default: Date.now
  }
})

const Todo = mongoose.model('Todo', todoSchema)
module.exports = Todo

server > src 폴더 내부에 models 폴더를 생성합니다. 또한 models 폴더 안에 Todo.js 파일을 생성하고 위와 같이 작성한다. 

스키마는 문서(Document)에 어떤 필드가 들어가고, 해당 필드의 데이터가 저장될 자료형은 무엇인지 등을 정의한다. 마치 객체를 생성하기 위하여 클래스(Class)를 정의하는 것과 유사하다. 이에 비해 모델은 스키마로부터 실제 메모리에 생성된 인스턴스이다. 스키마에서 required: true 로 설정된 부분은 사용자가 필수로 입력해줘야 하는 부분이다. 그렇지 않으면 오류가 발생한다. 

module.exports 는 node.js 에서 해당 파일을 외부에서 임포트해서 사용할 수 있도록 내보낸다. 현재는 메모리에 생성된 Todo 인스턴스를 외부에서 사용할 수 있도록 내보낸다. 

Todo 모델의 author 필드는 ObjectId 타입으로 정의하며 반드시 필요한 값으로 설정한다. ObjectId 는 MongoDB에서 부여한 도큐먼트의 고유한 ID 값이다. author 필드 타입을 ObjectId 타입으로 설정하면 사용자의 ID 값을 저장할 수 있다. ref 를 설정하면 추후 populate 메서드를 이용하여 사용자의 ID값으로 사용자의 전체 도큐먼트를 조회할 수 있다. 관계형 데이터베이스(RDBMS)의 Join 과 유사하다.

Todo 모델의 title 필드는 String 타입으로 정의하며 반드시 필요한 값으로 설정한다. trim: true 로 설정하여 title 문자열의 양쪽 공백을 제거한다. Todo 모델의 description 필드는 String 타입으로 정의하며 해당값은 사용자가 입력하지 않아도 되도록 설정한다. trim: true 로 설정하여 description 문자열의 양쪽 공백을 제거한다. 

Todo 모델의 isDone 필드는 Boolean 타입으로 정의하며 브라우저로부터 전달받은 값이 없으면 디폴트 값으로 false 를 저장한다. 

Todo 모델의 createdAt, lastModifiedAt, finishedAt 필드는 Date 타입으로 정의하며 브라우저로부터 전달받은 값이 없으면 디폴트 값으로 현재시간(Date.now) 을 설정한다. 

const mongoose = require('mongoose')

const { Schema } = mongoose
const { Types: { ObjectId } } = Schema

const todoSchema = new Schema({ // 스키마 정의
  author: {
    type: ObjectId, 
    required: true,
    ref: 'User'
  },
  title: {
    type: String,
    required: true,
    trim: true
  },
  description: {
    type: String,
    trim: true,
  },
  isDone: {
    type: Boolean,
    default: false,
  },
  createdAt: {
    type: Date,
    default: Date.now,
  },
  lastModifiedAt: {
    type: Date,
    default: Date.now,
  },
  finishedAt: {
    type: Date,
    default: Date.now
  }
})

const Todo = mongoose.model('Todo', todoSchema)
module.exports = Todo

// todo 데이터 생성 테스트
// const todo = new Todo({
//   author: '111111111111111111111111', // 24자리
//   title: ' 주말에 공원 산책하기  ',
//   description: '주말에 집 주변에 있는 공원에 가서 1시간동안 산책하기',
// });
// todo.save().then(() => console.log('todo created !'));

todo 스키마를 이용하여 데이터베이스에 제대로 todo 데이터가 생성되는지 확인하기 위하여 위와 같이 주석으로 작성된 부분을 추가한다. ObjectId 는 24자리 고유한 값이므로 위와 같이 24자리 숫자를 문자열 형태로 작성한다. 작성하지 않은 필드는 default 값으로 자동설정된다. 

var express = require('express') // node_modules 내 express 관련 코드를 가져온다
var app = express()
var cors = require('cors') 
var logger = require('morgan')
var mongoose = require('mongoose')
var axios = require('axios')
// var todo = require('./src/models/Todo')

server 폴더 바로 아래에 있는 index.js 파일에 주석으로 처리한 부분을 추가한다. 테스트를 위하여 주석을 해제했다가 테스트가 끝나면 다시 주석처리하도록 한다. index.js 파일의 위치로부터 상대경로로 Todo.js 파일을 임포트한다. 이렇게 하면 "todo 데이터 생성 테스트"에 작성한 코드가 실행되면서 MongoDB 데이터베이스에 도큐먼트를 생성한다. 

서버를 재시작하면 위와 같이 새로운 todo 도큐먼트가 생성되었다고 표시된다. 

위와 같이 MongoDB Compass 에서 확인해보면 todos 라는 컬렉션이 생성되고 하나의 todo 도큐먼트가 생성된 것을 확인할 수 있다. 서버를 재시작할때마다 새로운 도큐먼트가 추가로 생성된다. 

 

* 데이터 모델 설계 - User 

필드명 설명 데이터 타입 비고
name 사용자 이름 String required: true
email 사용자 연락처 String required: true
userId 사용자 아이디 String required: true
password 사용자 비밀번호 String required: true
isAdmin 사용자의 관리자 여부 Boolean default: false
createdAt 사용자 가입날짜  Date default: Date.now
lastModifiedAt 사용자 정보 수정날짜  Date default: Date.now

 

* 데이터 모델 구현 - User 

const mongoose = require('mongoose')

const { Schema } = mongoose

const userSchema = new Schema({ // 스키마 정의
  name: {
    type: String,
    required: true,
  },
  email: {
    type: String,
    required: true,
    unique: true, // unique: 색인(primary key) email은 중복불가
  },
  userId: {
    type: String,
    required: true,
  },
  password: {
    type: String,
    required: true,
  },
  isAdmin: {
    type: Boolean,
    default: false,
  },
  createdAt: {
    type: Date,
    default: Date.now,
  },
  lastModifiedAt: {
    type: Date,
    default: Date.now,
  }
}) 

const User = mongoose.model('User', userSchema)
module.exports = User

src > models 폴더 안에 User.js 파일을 생성하고 위와 같이 작성한다.

스키마는 문서(Document)에 어떤 필드가 들어가고, 해당 필드의 데이터가 저장될 자료형은 무엇인지 등을 정의한다. 마치 객체를 생성하기 위하여 클래스(Class)를 정의하는 것과 유사하다. 이에 비해 모델은 스키마로부터 실제 메모리에 생성된 인스턴스이다. 스키마에서 required: true 로 설정된 부분은 사용자가 필수로 입력해줘야 하는 부분이다. 그렇지 않으면 오류가 발생한다. 

module.exports 는 node.js 에서 해당 파일을 외부에서 임포트해서 사용할 수 있도록 내보낸다. 현재는 메모리에 생성된 User 인스턴스를 외부에서 사용할 수 있도록 내보낸다. 

User 모델의 name 필드는 String 타입으로 정의하며 반드시 필요한 값으로 설정한다.

User 모델의 email 필드는 String 타입으로 정의하며 반드시 필요한 값으로 설정한다. unique: true 로 설정하면 관계형 데이터베이스(RDBMS)에서의 색인(primary key) 처럼 럼 email 필드를 기준으로 데이터를 구분할 수 있는 고유한 값으로 인식한다. 

User 모델의 userId,  password 필드는 String 타입으로 정의하며 반드시 필요한 값으로 설정한다.

User 모델의 isAdmin 필드는 Boolean 타입으로 정의하며, 브라우저에서 전달받은 값이 없으면 디폴트 값을 false 로 설정한다. 

User 모델의 createdAt, lastModifiedAt 필드는 Date 타입으로 정의하며 브라우저로부터 전달받은 값이 없으면 디폴트 값으로 현재시간(Date.now) 을 설정한다. 

const mongoose = require('mongoose')

const { Schema } = mongoose

const userSchema = new Schema({ // 스키마 정의
  name: {
    type: String,
    required: true,
  },
  email: {
    type: String,
    required: true,
    unique: true, // unique: 색인(primary key) email은 중복불가
  },
  userId: {
    type: String,
    required: true,
  },
  password: {
    type: String,
    required: true,
  },
  isAdmin: {
    type: Boolean,
    default: false,
  },
  createdAt: {
    type: Date,
    default: Date.now,
  },
  lastModifiedAt: {
    type: Date,
    default: Date.now,
  }
}) 

const User = mongoose.model('User', userSchema)
module.exports = User

// user 데이터 생성 테스트
// const user = new User({
//   name: '태양',
//   email: 'sun@gmail.com',
//   userId: 'sunrise',
//   password: '1234567890',
//   isAdmin: true,
// });
// user.save().then(() => console.log('user created !'));

user 스키마를 이용하여 데이터베이스에 제대로 user 데이터가 생성되는지 확인하기 위하여 위와 같이 주석으로 작성된 부분을 추가한다. isAdmin: true 로 설정하여 관리자 권한을 부여한다. 작성하지 않은 필드는 default 값으로 자동설정된다. 

var express = require('express') // node_modules 내 express 관련 코드를 가져온다
var app = express()
var cors = require('cors') 
var logger = require('morgan')
var mongoose = require('mongoose')
var axios = require('axios')
// var user = require('./src/models/User')

server 폴더 바로 아래에 있는 index.js 파일에 주석으로 처리한 부분을 추가한다. 테스트를 위하여 주석을 해제했다가 테스트가 끝나면 다시 주석처리하도록 한다. index.js 파일의 위치로부터 상대경로로 User.js 파일을 임포트한다. 이렇게 하면 "user 데이터 생성 테스트"에 작성한 코드가 실행되면서 MongoDB 데이터베이스에 도큐먼트를 생성한다. 

서버를 재시작하면 위와 같이 새로운 user 도큐먼트가 생성되었다고 표시된다. 

위와 같이 MongoDB Compass 에서 확인해보면 users 라는 컬렉션이 생성되고 하나의 user 도큐먼트가 생성된 것을 확인할 수 있다. 서버를 재시작할때마다 새로운 도큐먼트가 추가로 생성된다. 

728x90