mongoDB + Postman + vue

국비 코딩 풀스택 수업 14일차

비루블 2022. 7. 11. 13:53

정리

백엔드 시작(기본 모듈 및 프로그램 설치, 프로젝트 생성)

몽고디비 mongoDB 설치(서버정보 기입)

포스트맨 Postman 설치(프론트가 안만들어졌는데, 백엔드 작업하려고, app.vue에 서버정보 기입)

vue가 express에 들어감(?)

package.json(서버 실행 간단하게 만들기)

req(프론트에서 받는 정보), res(보내줄떄)

index.js 하나에 다 짜면 데이터 양 많아지면 힘듬 그래서 routes에 여러가지 공간들로 나눔

mvc패턴(모델, 뷰, 컨트롤러)

bookmodel + book

book에서 post로 보내는 것은 body에 담겨서 옴.

database와 연결 app.js

erd 다이어그램(설계 도면), 우리는 다이어그램의 큰 프로젝트중 아주 작은 하나를 하고 있는 것.

 

원리

bookmodel에서 정보가 넘어와서
book.js에서 사용 (book.js 입장에서는 req)
받아 온것을 book에 넣고
실제 db에 저장

 

Postman 포스트맨에서 데이터 조회(get)

 


오전일과

모듈, 프로그램 설치

프로젝트 폴더 생성

https://nosqlbooster.com/downloads
https://www.postman.com/

몽고디비(데이터 베이스에 접속하기위한 프로그램)
서버 + 포트 + 아이디 비번 입력

백엔드 시작
d>express or next 만들기>
--------------------------------
-- express 프로그램 설치
CMD> npm i express-generator -g

-- express 설치 확인
CMD> express --version
    => 4.16.1

-- project 생성 폴더명(exp_20220711)
CMD> express -e exp_20220711


-- project01 폴더로 이동
CMD> cd exp_20220711

-- 관련 라이브러리 설치
CMD> npm install

-- 서버 구동
CMD> npm start

-- 크롬의 주소창에 127.0.0.1:3???을 입력해서 결과화면 확인
------------------------------

- npm start로 구동하면 소스코드 변경시 서버를 재구동해야 함.
- 자동으로 서버를 재시작 되도록 nodemon을 설치해서 서버를 구동함.
CMD> npm install nodemon -g

CMD> nodemon --version
 설치된 버전2.0.4

- 실행파일은 ./bin/www파일을 실행 시킴. 종료는 ctrl+c를 누름
CMD> nodemon --inspect ./bin/www


------------------------------------------------
뷰가 익스프레스에 들어감(통합)


npm start뜻
package.json에 있는 start의 부분을 실행하는 것임
cmd > node ./bin/www 치는거랑 똑같은 말임.(쉽게하려고)

{
  "name": "exp-20220711",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "nodemon --inspect ./bin/www"
  },
  "dependencies": {
    "cookie-parser": "~1.4.4",
    "debug": "~2.6.9",
    "ejs": "~2.6.1",
    "express": "~4.16.1",
    "http-errors": "~1.6.3",
    "mongoose": "^6.4.4",
    "mongoose-sequence": "^5.3.1",
    "morgan": "~1.9.1"
  }
}



우리가 필요한 것은 아래것.
CMD> nodemon --inspect ./bin/www 
위에처럼 직접 안치고
package.json에서 start부분에 넣어놓으면
cmd에서 npm start만 쳐도 nodemon --inspect ./bin/www 이것으로 알아먹음

 


백엔드 폴더속 views에
프론트엔드가 들어가는 것임.


routes>index.js

출력 확인

// 크롬에서 127.0.0.1:3???/abc.json 서버주소
router.get('/abc.json', function(req, res, next) {
  const data = {userid:'abc'} //만들고
  res.send(data); //보내주기
});


접속시 {"userid" : "abc"} 가 뜸.

 


req가 프론트엔드에서 정보를 받는 것.(req로 옴)
백엔드 입장 req는 in, res는 out

쿼리 확인
http://127.0.0.1:3???/abc.json?id=aaa
console.log(req.query);

 


포스트맨 사용
프론트가 안만들어졌는데, 백엔드 작업하려고


index.js 업무단위
index.js에 다 짜면 찾기 어려움.
그래서 따로 파일로 만들어서 코드를 나눔 중요중요

but
같은 주소를 쓰면 오류가 뜸.(충돌)
users는 따로 공간이 존재
http://127.0.0.1:3000/users/
따로 공간 존재 확인(app.js에 22번,23번줄 사진 확인)



.js로 공간을 만들면 app.js에 넣어야함.
127.0.0.1:3???/여기/ 여기부분을 파일명으로 넣음.

var boardRouter = require('./routes/board');
var bookRouter = require('./routes/book');


app.use('/board', boardRouter);
app.use('/book', bookRouter);


board.js만듬
app.js에 등록

book.js에

서버 정상 및 불량 처리 return 활용
오류 발생방지 try, catch 사용법 status : -1
성공시 status : 200

router.post('/insert.json', async function(req, res, next) {
    try{
        //실제로 db에 저장하기
        const result = await book.save();

        if(result !== null) {
            return res.send({status:200, result:result});
        }
        return res.send({status:0})
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e})
    }
});

 



database와 연동
어디서?
app에서 database와 연결

CMD>npm i mongoose --save

app.js

// mongodb 연결하기
// CMD > npm i mongoose --save
var mongoose = require('mongoose');


//아이디:암호@서버주소:포트번호/DB명
mongoose.connect('mongodb://id???:pw???@1.???.?.158:37017/db???')
var db = mongoose.connection;
db.once('open', function(){
  console.log('db연결 성공');
})


폴더 만들기 models

bookmodel.js
mvc패턴이다 하는데
m은 모델 model
v는 뷰 vue
c는 컨트롤러 controller


models>bookmodel.js
중요중요중요중요중요중요중요중요중요

// npm i mongoose --save
var mongoose = require('mongoose');
// npm i mongoose-sequence --save
const AutoIncrement = require('mongoose-sequence')(mongoose);

var Schema = mongoose.Schema;
var bookSchema =  new Schema({
    _id     : Number, //책번호, 고유값, 기본키, 자동증가
    title   : {type:String, default:''},//제목
    author  : {type:String, default:''}, //저자
    price   : {type:Number, default:0},  //가격
    regdate : {type:Date, default:Date.now} //등록일, 현재시간으로 등록
});

bookSchema.plugin(AutoIncrement, 
    {id:"SEQ_BOOK_ID", inc_field:'_id'});
module.exports = mongoose.model('book', bookSchema);

위와 아래는 크게 볼 필요는 없고(SEQ_BOOK_ID는 게시물들 아이디 생성때 시퀀스 이용하여 넘버를 자동 + 1)

new Schema부분이 중요


erd 다이얼그램(설계도면) 중 아주 작은 하나를 우리가 실습하고 있는 것임.


book.js
post
post로 보내는 건 body에 담겨서 옴

post + 서버주소 사용 업로드 및 게시글 추가

 


원리 중요중요중요
북모델
var 북쉬마
SEQ_BOOK_ID 이게 db에 counters에 생김
게시글을 올릴 때마다 seq가 올라감

var 북쉬마가 중요(설계임) 
bookmodel에서 정보가 넘어와서
book.js에서 사용 (book.js 입장에서는 req)
받아 온것을 book에 넣고
실제 db에 저장

 

상세설명(이번 과정으로 설명)
(
postman에서 임의로 데이터 업로드
{"title":"a3214aa", "author":"bb2314b", "price":1223421433}
127.0.0.1:3???/book/insert.json (push)
bookemodel.js에 정보가 넘어옴
book.js에서 양식에 맞게 데이터 형성
넘버(아이디), 날짜는 두고 제목, 저자, 가격만 업로드

 

status200 정상
)


추가 post
조회 get
수정 put, patch
삭제 delete


이제 조회
book.js

get + 서버 주소 게시글 조회

router.get('/select.json', async function(req, res, next) {
    try {
        const result = await Book.find({});
        const data = {status:200, result:result};
        return res.send(data)
    }
    catch(e) {
        console.error(e);
        return res.send({status:-1, result:e})
    }
  });




오후 일과


book.js 중요중요중요
delete
//127.0.0.1:3???/book/delete.json?no=1 ->req.query.no
//?no=1 <<파라미터로 오는건 쿼리로 옴 (쿼리로 줌)

?no=9

router.delete('/delete.json', async function(req, res, next) {
    try {
        //삭제하기 위한 조건 _id 가 일치하는 것
        const query = {_id : Number(req.query.no)};
        const result = await Book.deleteOne(query);
        console.log(result);

        const data = {status:200, result:result};
        return res.send(data)
    }
    catch(e) {
        console.error(e);
        return res.send({status:-1, result:e})
    }
  });



update 중요중요중요

//127.0.0.1:3???/book/update.json
//{"no":4, "title":"bbb", "price":1234} => req.boy.no, req.body.title
내용을 쿼리로 준게 아니라 바디로 줌

router.put('/update.json', async function(req, res, next) {
    try {
        // 1. 기존에 있는 값 가져오기
        const query = { _id : Number(req.body.no) };
        const book  = await Book.findOne(query);

        // 2. 변경할 요소만 설정
        book.title = req.body.title;
        book.price  = Number(req.body.price);

        // 3. DB변경
        const result = await book.save();

        const data = {status:200, result:result};
        return res.send(data);
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});

 


수정은

1. 기존에 있는 값을 가져오기
2. 변경할 요소만 설정
3. DB변경


(
수정은 1. 기존에 있는 값을 가져오기
const query = {_id : Number(req.query.no)};
const book = await Book.findOne(query);
2. 변경할 요소만 설정
book.title = recv.title;
book.author = recv.author;
book.price = Number(recv.price);
3.DB변경
const result = await book.save();
)

 

delete put
쿼리사용, 바디사용


만든걸 기반으로 vue 만들기
vue.confi.js 설정

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,

  devServer : {
    proxy : {
      // 127.0.0.1:3000/book/~~~~
      '/book': {
        target : 'http://127.0.0.1:3???',
        changeOrigin : true,
        logLevel : 'debug'
      },
    }
  }
  
})


routes>index.js 설정

// CMD> npm i vue-router@next --save
import { createWebHashHistory, createRouter} from 'vue-router';

import BookInsert from '@/components/BookInsert.vue';
import BookSelect from '@/components/BookSelect.vue';
import BookUpdate from '@/components/BookUpdate.vue';

const routes =  [
    {path:'/bookinsert', component:BookInsert},
    {path:'/bookselect', component:BookSelect},
    {path:'/bookupdate', component:BookUpdate}
];

//라우트객체 생성
const router = createRouter({
    history : createWebHashHistory(),
    routes : routes,
});

export default router;


components 생성

BookSelect.vue 책, 북 게시판 목록

<template>
    <div>

        <button @click="handleInsert">등록하기</button>
        <table>
            <tr v-for="tmp of state.rows" :key="tmp._id">
                <td>{{tmp._id}}</td>
                <td>{{tmp.title}}</td>
                <td>{{tmp.author}}</td>
                <td>{{tmp.price}}</td>
                <td>{{tmp.regdate}}</td>
            </tr>

        </table>
    </div>
</template>

<script>
import { reactive } from '@vue/reactivity'
import axios from 'axios';
import { onMounted } from '@vue/runtime-core';
import { useRouter } from 'vue-router';
export default {
    setup () {
        const router = useRouter();
        const state = reactive({
            rows:[],
        });
        const handleData = async() => {
            const url = `/book/select.json`;
            const headers = {"Content-Type" : "application"};
            const {data} = await axios.get(url, {headers});
            console.log(data);
            if(data.status === 200){
                state.rows =data.result;
            }
        };

        const handleInsert = () => {
            router.push({path:'/bookinsert'});
        };

        onMounted(() =>{
            handleData();
        });


        return {state, handleInsert}
    }
}
</script>

<style lang="scss" scoped>

</style>

BookInsert.vue 책, 북 글쓰기

<template>
    <div>
        <input type="text" v-model="state.title" />
        <input type="text" v-model="state.author" />
        <input type="text" v-model="state.price" />
        <button @click="handleInsert">등록</button>
    </div>
</template>

<script>
import { reactive } from '@vue/reactivity'
import { useRouter } from 'vue-router';
import axios from 'axios';
export default {
    setup () {
        const router = useRouter();
        const state = reactive({
            title : '',
            author : '',
            price : 0,
        });
        

        const handleInsert = async() => {
            const url = `/book/insert.json`;
            const headers = {"Content-Type" : "application/json"}
            const body = {
                title : state.title,
                author : state.author,
                price : state.price,
            }
            const {data} = await axios.post(url, body, {headers});
            console.log({data});
            if(data.status === 200){
                alert('게시물 등록')
                router.push({path:'/bookselect'});
            }

        };

        return {state, handleInsert}
    }
}
</script>

<style lang="scss" scoped>

</style>

 

main.js설정

import { createApp } from 'vue'
import App from './App.vue'

import routes from './routes/index.js'

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App);
app.use(routes);
app.use(ElementPlus);
app.mount('#app');


인터페이스 만들기