[Express] Mongoose 구성하기

(Nuxt.js 프로젝트에) Express를 미들웨어로 사용하여 Mongoose를 통해 MongoDB에 연결하였음을 전제로 시작합니다.

흐름만 파악할 수 있는 간단한 예제를 구성했습니다. 실제로는 유효성 검사 등도 필요할 것입니다.

Model(Schema) 만들기

  • MongoDB는 기본적으로 Schema-less한 DB이지만 필요하다면 아래처럼 구성할 수 있다.
    • Schema: 검색하면 이게 대체 뭔 소리야 싶은 정보가 많이 나오는데,
      쉽게는 "각 테이블에 어떤 자료형의 어떤 데이터들이 저장되는지, 테이블간의 관계는 어떻게 되는지를 나타내는 개요도" 정도로 이해하면 될 것 같다.

    • 그러니까, schema-less 하다는 말은

      • 각 '테이블'에 저장되는 데이터의 형태가 정해져있지 않다.
      • 각 '테이블'간의 참조관계가 없다.
      • 그래서 MongoDB에서는 '데이터'의 '테이블'이 아니라 'document'의 'collection'이라는 명칭을 쓴다.
    • (아래에서 구성하는 schema는 사실 단일 '테이블' 만들기로 보인다.)

      // <root>/api/models/user.js
      const bcrypt = require('bcrypt'); // npm install bcrypt로 설치
      const saltRound = 10; // bcrypt 모듈에 사용되는 인수
      const mongoose = require('mongoose');
      const Schema = mongoose.Schema;
      
      const userSchema = new Schema({
        userid: { type: String, required: true, unique: true },
        name: { type: String, required: true },
        password: { type: String, required: true },
        create_date: { type:Date, default:Date.now }
      });
      
      // schema에 method나 statics를 추가하면 SQL의 '저장 프로시저'처럼 사용할 수도 있다.
      // 둘의 차이는 (public) instance method와 static method의 차이와 같음
      userSchema.statics.create = function (_user) {
        const user = new this({
          userid: _user.userid,
          name: _user.name,
        });
        
        // 비밀번호 암호화 작업
        user.password = bcrypt.hashSync(_user.password, saltRound);
        
        return await user.save()
          .then(function (document) {
            return document._id;
          })
          .catch(function (err) {
            return Promise.reject(err);
          });
      }
      
      module.exports = mongoose.model('User', userSchema);

unique 속성은 null값 등도 어쨌든 값으로 보기 때문에, 동일하게 null값을 갖는 doucment를 생성할 수 없다는 ERROR E11000 duplicate key error collection를 발생시킬 수도 있다.
required 속성 등으로 해결하자.

아이디 필드 명을 id로 해버리면 find 등의 쿼리가 제대로 동작하지 않으니 다른 이름을 사용하길 추천한다.

Model을 이용한 API 처리

  • function (req, res)을 구현할 곳에 해당 Model을 import하며 시작한다.
    (<root>/api/index.js라든가, <root>/api/routes/users.js라든가, <root>/api/controllers/usersController.js라든가..)
    // 이 예시는 <root>/api/routes/users.js 에서 처리하는 것으로.
    const { router } = require('express');
    const User = require('../models/user');
    
    router.post('/register', function (req, res) {
      User.create(req.body.user)
        .then(function (response) {
          return res.json(response);
        })
        .catch(function (err) {
          return res.status(500).send(err);
        });
    });
    
    module.export = router;
  • 최종적으로는 Promise가 아니라 res를 리턴해야 함을 잊지 말자. 그렇지 않으면 (axios 등에서) 제대로 된 response를 받을 때까지 대기하는 상태가 되어버린다.

vue 페이지

  • 해당 route로 parameter를 쉽게 넘겨줄 수 있도록 위에서 만든 schema를 본따
    {
      user: {
        userid: '',
        name: '',
        password: '',
      }
    }
    형태의 데이터 모델을 관련 view에서도 사용한다.
    (user로 묶지 않아도 크게 상관은 없는 것 같
  • 제출 메소드는 아래와 같은 형태로 작성한다. (axios 패키지 필요)
    method: {
      submitForm() {
        const self = this; // 콜백함수 안에서는 this의 대상이 바뀌기 때문에
        self.$axios.post('/api/users/register')
          .then(function (res) {
            if (res.data._id) {
              alert('성공!');
              self.$router.push({
                path: '/',
              });
            } else {
              alert('등록 실패');
              console.log(response);
            })
          .catch(function (err) {
            console.log(err.response);
            // 
          });
        },
      },

참고한곳

좋은 웹페이지 즐겨찾기