본문 바로가기

백엔드

[Node.js] 6. 서버와 MongoDB 연결하기

MongoDB

MongoDB는 NoSQL 데이터베이스로 기존에 학습한 MySQL의 관계형 데이터베이스와 데이터를 저장한다는 점을 제외하고는 완전히 다르다. NoSQL은 컬렉션(SQL의 테이블)과 문서(SQL의 로우)로 구성된다. SQL은 일관성 측면에서 특장점이 있고, NoSQL은 확장성에 이점이 있다.

 

MongoDB 설치 및 세팅

먼저 설치는 https://www.mongodb.com/download-center/community에서 진행할 수 있다. 계속 next를 하고 중간에 좌측 하단에 Install MongoDB Compass도 체크하여 설치한다. 

 

설치가 완료되면 시스템 변수의 path에 MongoDB의 경로인 C:\Program Files\MongoDB\Server\4.4\bin을 추가해준다. 그리고 터미널을 열어 해당 폴더로 이동한다. 

 

MongoDB의 실행

cd C:\Program Files\MongoDB\Server\4.4\bin
mongod

 

MongoDB를 매번 실행하는게 귀찮다면 서비스로 추가하여 컴퓨터가 부팅 시 자동으로 시작하게 만들면 된다. 방법은 먼저 C드라이브 밑에 data 폴더를 만들고 data 폴더 밑에 db와 log 폴터를 생성한다. 그리고 MongoDB가 설치된 경로로 이동하여 터미널을 관리자 권한으로 실행하고 아래 커맨드를 입력한다.

mognod --dbpath C:\data\db --logpath C:\data\log\log.txt --install --serviceName "MongoDB"

 

그리고 services.msc를 입력하고 MongoDB를 찾아 우측에 시작을 클릭한다.

 

이제 실제 MongoDB의 프롬프트에 접속하기 위해 터미널에 mongo를 입력하고 계속해서 기본 유저를 생성한다.

mongo

use admin

db.createUser({user:이름, pwd:비번, roles:['root']})

 

이제 기본적인 DB생성, 컬렉션 생성, 문서 생성 명령어를 알아본다. 아래 명령어는 DB를 생성하여 해당 DB 내에 user 컬렉션을 생성하고 실제 유저 문서(데이터)를 추가하는 예시이다.

use test;
db.createCollection('user');
db.user.save({name:'kang', age:24, married:false});

 

다음은 조회, 수정, 삭제 예제이다.

db.user.find({}); //전체 유저 반환
db.user.find({age:{$gt:30},married:true},{name:1, age:1});// 30세 이상의 결혼한 유저의 이름, 나이
db.user.find({$or:[{age:{$gt:30}},{married:true}]},{name:1, age:1});// 30t세 이상이거나 결혼한 유저의 결혼한 유저의 이름, 나이

db.user.update({name:'kang'}, {$set:{married:ture}});

db.user.delete({name:'kang'});

Mongoose

MongoDB는 스키마가 존재하지 않아 자유로운 데이터 입출력이 가능하지만, 이는 문제 발생의 요지가 많음을 의미한다. 이를 방지하기 위해 몽구스를 사용한다. 몽구스는 컬렉션의 스키마를 정의하여 정해진 문서만 삽입할 수 있게 하는 라이브러리이다.

 

npm install mongoose

 

이제 실제로 서버와 MongoDB를 연결해보자. 먼저 프로젝트 폴더에 schema 폴더를 생성하고 그 안에 index.js를 생성하여 아래와 같이 작성한다. 7번 라인의 코드에서 'mongodb://유저:비밀번호@localhost:27017/admin'으로 작성하기 바란다.

const mongoose = require('mongoose');

const connect = () =>{
    if(process.env.NODE_ENV !== 'production'){ //개발환경일 경우에만 콘솔 출력
        mongoose.set('debug',true);
    }
    mongoose.connect('mongodb://유저:비밀번호@localhost:27017/admin',{
        dbName:'test',
        useNewUrlParser: true,
        useUnifiedTopology: true,
        useCreateIndex: true,
    }, (error)=>{
        if(error)
            console.log('mongodb connect error', error);
        else
            console.log('mongodb connect');
    });
};

mongoose.connection.on('error', (error)=>{
    console.log('mongodb connect error', error);
});
mongoose.connection.on('disconnected',()=>{
    console.log('mongodb id disconnected. Tying to connect again');
    connect();
});

module.exports = connect;

 

그 이후 server.js에 schema/index.js를 연결한다.

const express = require("express");
const app = express();
const connect = require('./schemas');


connect();


app.listen(3000, () => { //3000번 포트
    console.log("the server is running")
});

 

이제 실제 사용할 스키마를 정의한다. schema 폴더 밑에  club.js를 생성한다.

const mongoose = require('mongoose');

const {Schema} = mongoose;
const clubSchema = new Schema({
    name:{
        type: String,
        required: true,
    },
    image:{
        type: String,
    },
    manager_uid_list:[
        {
            type:Schema.ObjectId,
            ref:"User"
        }
    ],
    certification:{
        type: Boolean,
        default: false,
    },
    classfication:{
        type: String,
    },
    member_count:{
        type: Number,
        default: 0,
    },
    member_uid_list:[
        {
            type:Schema.ObjectId,
            ref:"User"
        }
    ]
});

module.exports = mongoose.model('Club', clubSchema);

MongoDB의 자료형은 String, Number, ObjectId, Date, Boolean, Array 등이 존재한다. required가 true라면 그 필드믄 무조건 존재해야 한다. 그리고 ObjectId는 다른 컬렉션에 존재하는 ID를 참조할 때 사용된다. 기본적으로 문서 자체적으로 ObjectId가 생성된다. 그리고 컬렉션 이름은 마지막 줄에서 'Club'이라고 작성했으면 'clubs'로 정의된다.

 

라우터 작성 routes/club.js를 생성하고 아래와 같이 작성한다.

const express = require('express');
const Club = require('../schemas/club');
const multer = require('multer');
const path = require('path');
const fs = require('fs');

const router = express.Router();

router.get('/',async(req,res,next)=>{
    try{
        const club = await Club.find({});
        res.send(club);
        //const result = await Club.populate(club, {path:'member_uid_list'});
    }catch(err){
        console.error(err);
        next(err);
    }
});


router.post('/',async(req,res,next)=>{
    try{
        const club = await Club.create({
            name: req.body.name,
            image: req.body.image,
            president_uid: req.body.president_uid,
            member_uid_list: req.body.member_uid_list,
            certification: req.body.certification,
            type:req.body.type,
            classfication:req.body.classfication,
            member_count:req.body.member_count,
            member_uid_list:req.body.member_uid_list,
            recruitment:req.body.recruitment
        });
        res.send(club);
        //const result = await Club.populate(club, {path:'member_uid_list'});
    }catch(err){
        console.error(err);
        next(err);
    }
});

router.delete('/:name',async(req,res,next)=>{
    try{
        const club = await Club.remove({name:req.params.name});
        res.send(club);
        //const result = await Club.populate(club, {path:'member_uid_list'});
    }catch(err){
        console.error(err);
        next(err);
    }
});


module.exports = router;