20220729 [ERD, model]

Yeoonnii·2022년 7월 30일
0

TIL

목록 보기
3/52
post-thumbnail

내가 등록한 물품목록 조회 서버만들기

📁routes/ex_sell.js

설계도면에서 필요한 정보 확인하기

커뮤니티에 가입된 판매자의 정보 가져오기

item ➡️ sell ➡️ community ➡️ register➡️ member
테이블 순서로 판매자의 정보를 파악한다

sell 테이블에 참조된 커뮤니티 번호가 로그인 한 사용자의 것인지 register 테이블에서 확인한다
조회 조건 ➡️ 로그인 token + 조회하고자 하는 communityno

register 테이블에서 로그인한 사용자의 커뮤니티가 맞다면
sell 테이블에서 로그인한 사용자
➡️ 커뮤니티 번호와 일치하는 데이터(itemno)모두(find) 가져온다
💡 chk값(판매중 chk=1, 판매중지 chk=0)에 관계없이 모든값을 조회

  • sell 테이블 데이터 조회시
    itemno(FK)는 필요 조건이 아니라 가져올 결과값이다

  • community 테이블과 item테이블은 관계가 없지만
    sell테이블로 인해 관계가 생긴다


💻Restaurant Project - ERD

배달어플 로직과 비슷하게 구현

📁exp_20220711/prj2.vuerd.json
(새 테이블 생성시 Database > Oracle로 변경 후 작성)

📑 restaurant 테이블

사업자등록번호를 기본키로 사용
➡️ 상호명을 기본키로 쓸 수 없다! 동일한 이름의 식당이 있을 수 있기 때문

📑 food 테이블

restaurant 테이블과 food 테이블은 1:N 관계
= 하나의 식당(restaurant)은 여러개의 음식(food)를 가질 수 있다

📑 order 테이블

food 테이블과 customer 테이블을 연결해주는 동적(action) 테이블이다.

📑 고객테이블

고객아이디 => 고객의 연락처를 기본키로 사용한다

💡 fd_food, fd_order테이블의 기본키만 자동번호(SEQ) 부여한다

password는 앱에서는 필요 없지만 인증 방법이 달라 pc에서는 필요하다
서버생성시 고객인증 기능까지 추가하기!


💻Restaurant Project - model

ERD 참조하여 모델 생성

📁exp_20220711/models/food

  • fd_categorymodel.js
  • fd_customermodel.js
  • fd_foodmodel.js
  • fd_ordermodel.js
  • fd_restaurantmodel.js

💡 model생성시 외래키(FK) 값도 설정해줘야한다!

📁exp_20220711/models/food/fd_restaurantmodel.js

var mongoose = require('mongoose');

var Schema = mongoose.Schema;
var restaurantSchema =  new Schema({
    _id           : String,                        // 사업자번호(PK)
    name          : {type:String, default:''},     // 상호
    phone         : {type:String, default:''},     // 연락처
    address       : {type:String, default:''},     // 주소
    regdate       : {type:Date, default:Date.now}, // 등록일
    categorycode  : {type:String, default:''},     // 카테고리코드(FK)
    password      : {type:String, default:''},     // 암호(FK)
});

module.exports = mongoose.model('fd_restaurant', restaurantSchema);

모델생성 완료 후 서버 생성

📁exp_20220711/routes/food/

  • fd_restaurant.js
  • fd_category.js

model 등록시 파일경로에 맞게 상위경로로 한번 더 이동한다

var Category = require("../../models/food/fd_categorymodel");
var Restaurant = require("../../models/food/fd_restaurantmodel");

서버 생성 완료 후 APP.js 에 등록

📁exp_20220711/app.js

var fd_restaurantRouter = require('./routes/food/fd_restaurant');  
var fd_categoryRouter = require('./routes/food/fd_category');  

app.use('/api/fd_restaurant', fd_restaurantRouter);  
app.use('/api/fd_category', fd_categoryRouter);  

저장 후 cmd에 오류가 없다면 DB에 컬렉션이 생성된것을 확인 할 수 있다.


mongodb에 수동으로 카테고리 추가

db.fd_categories.insertMany([
    {_id:'A', content:'한식', regdate:new Date()},
    {_id:'B', content:'중식', regdate:new Date()},
    {_id:'C', content:'일식', regdate:new Date()},
    {_id:'D', content:'양식', regdate:new Date()},
    {_id:'E', content:'분식', regdate:new Date()},
]);


전체 카테고리 조회

category 모델 생성

📁exp_20220711/models/food/fd_categorymodel.js

//nodejs mongodb ORM기반 모듈
var mongoose = require("mongoose");


var Schema = mongoose.Schema;
var categorySchema = new Schema({
    _id           :  String, // 기본키, 분류코드(3자리 =>AAA,BBB,CCC)

    content       : { type: String, default: "" },  // 내용
    regdate       : { type: Date, default: Date.now }, // 가입일, 디폴트값 : 현재시간 

});


//몽고 DB에 컬렉션 생성
module.exports = mongoose.model("fd_category", categorySchema); 

전체 카테고리 조회 서버 생성

📁exp_20220711/routes/food/fd_category.js

var express = require("express");
var router = express.Router();

var Category = require("../../models/food/fd_categorymodel");



// 전체 카테고리 조회
// 127.0.0.1:3000/api/fd_category/select.json
router.get("/select.json",async function (req, res, next) {
    try {
        const result = await Category.find({}).sort({_id:1});

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


module.exports = router;

App.js에 category 라우트 등록 되었는지 다시 확인

📁exp_20220711/app.js

var fd_restaurantRouter = require('./routes/food/fd_restaurant');  
var fd_categoryRouter = require('./routes/food/fd_category');  

app.use('/api/fd_restaurant', fd_restaurantRouter);  
app.use('/api/fd_category', fd_categoryRouter);  

restaurant 등록(가입)서버

📁exp_20220711/routes/food/fd_restaurant.js

식당등록 = 회원가입과 같다
식당이 곧 사람이라고 생각하면 된다!

// 식당이 곧 사람 = 개체 
// 127.0.0.1:3000/api/fd_restaurant/insert.json
// {"id" : "", "name" : "", "phone" : "", "address" : "", password:""}
router.post("/insert.json", async function (req, res, next) {
    try {  
        // 암호정보 hash
        const hashPw = crypto.createHmac( 'sha256', req.body._id + auth.hashSalt ).update( req.body.password ).digest('hex');
        // 저장할 객체 생성
        const obj = new Restaurant();
        obj._id = req.body._id
        obj.name = req.body.name;
        obj.phone = req.body.phone;
        obj.address = req.body.address;
        obj.categorycode = req.body.categorycode;
        obj.password = hashPw;

        // console.log('obj => ', obj);
        const result = await obj.save();
        console.log(result);
        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 }); 
    }
  });

restaurant 로그인 서버

토큰파일 생성

📁exp_20220711/token/fd_auth.js 생성 (로그인 후 반환될 토큰)

// 1. 모듈설치 CMD> npm i jsonwebtoken --save
const jwt = require("jsonwebtoken");

// 토큰 발행용 정보 설정=> 토큰 검증, 토큰 반환

const fd_auth = {
  //회원가입, 로그인시 hash salt값
  hashSalt : "a#$sdfwe$^rwqwe", 

    //salt값과 비슷함! 토큰 발행시 쓰는 salt값이라 생각하면 된다!
    securitykey: "asdfETWei!@#_%3354erw", 

    //토큰 발행시 옵션
    options: {
      algorithm: "HS256", // 토큰 생성 알고리즘 종류
      expiresIn: "10h", // 토큰 유효 시간 (10시간=>10h 설정)  ex) 30분단위 설정시 => 30m
      issuer: "ds_corp", // 발행자
    },
  
    //데이터 들어오면 토큰에 넣어 반환시켜주는 역할
    // DATA변수에 토큰에 포함하고자 하는 정보를 전달
    generateToken: (data) => {
      //{FID:'aaa'}
      // const token = jwt.sign(data, auth.securitykey, auth.options);
      // return token;//위 두줄을 아래 한줄과 같이 쓸 수 있음!
      return jwt.sign(data, fd_auth.securitykey, fd_auth.options);
    },
  
};

module.exports = fd_auth; // 마지막에 export해줘야 다른폴더에서 사용가능!

fd_auth.js 생성후 로그인 서버 생성

📁exp_20220711/routes/food/fd_restaurant.js

  • fd_auth 파일경로 확인하여 작성
const auth = require('../../token/fd_auth'); // fd_auth.js가져오기


// 식당 로그인 (=> 해야만 메뉴 등록가능)
// 127.0.0.1:3000/api/fd_restaurant/selectcategory.json
// {"_id":"사업자등록번호", "password":"암호"}
router.post("/selectcategory.json",async function (req, res, next) {
    try {
        
        const _id = req.body._id;
        const hashPw = crypto.createHmac( 'sha256', req.body._id + auth.hashSalt ).update( req.body.password ).digest('hex');
        
        const project = { _id : 1};
        const query = { _id : _id, password:hashPw };

        const result = await Restaurant.findOne(query).select(project);

        console.log(result);

        if(result !== null){
            // 토큰에 포함할 내용(아이디와 권한정보(식당인지 고객인지))
            const data = { "FID" : result._id, "ROLE":"RESTAURANT" }
            // 토큰 생성
            const token = auth.generateToken(data);
            // 결과반환 
            return res.send({ status: 200, token:token });
        }

        
        return res.send({ status: 0 }); //위 조건 조회 후 결과가 없는경우 조회불가
      } catch (e) {
        //오류 발생시
        console.error(e); // 백엔드에게 알려주는 부분
        return res.send({ status: -1, result: e }); //프론트에게 알려주는 부분
      }
    });

💻Restaurant Project - Vue 프로젝트 생성

파일생성 및 프로그램 설치

CMD> vue create fd_restaurant

CMD> cd fd_restaurant
CMD> npm i axios --save
CMD> npm i vue-router@next --save
CMD> npm i vuex --save

vue.config.js에 proxy설정

📁vue/fd_restaurant/vue.config.js

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  devServer : {
    proxy : {
      '/api': {
        target : 'http://127.0.0.1:3000',
        changeOrigin : true,
        logLevel : 'debug'
      }
    },
    port:8081
  }
  
})

💡 프로젝트 생성시 백엔드 서버주소를 다르게 하면 페이지를 나눌 수 있다

  • 서버주소 : 3000/restaurant
    CMD> vue create fd_restaurant //회원용 vue
  • 서버주소 : 3000/
    CMD> vue create fd_customer //고객용 vue

💡 vue.config.js에서 port번호를 다르게 하면
여러개의 vue를 동시에 돌릴 수 있다

서버실행

CMD> npm run serve

메인화면 (App.vue)

식당용 페이지는 로그인페이지를 첫화면으로 구현하면 된다

고객용 페이지와는 다르게 많은 기능이 필요하지 않으며,
로그인 한 후에 사용할 수 있는 서비스가 대부분이기 때문에
로그인페이지가 메인페이지라고 생각하면 된다

라우트 폴더 및 파일 생성

📁vue/fd_restaurant/src/routes/index.js

import { createWebHashHistory, createRouter } from 'vue-router';

import Login from '@/components/restaurant/LoginPage.vue';
import Insert from '@/components/restaurant/InsertPage.vue';

const routes = [
    {path:'/', redirect:'/login'},
    {path:'/login', component:Login},
    {path:'/insert', component:Insert},
];

const router = createRouter({
    history : createWebHashHistory(),
    routes  : routes,
});

//페이지 이동경로추적 from에서 => to로 이동
router.beforeEach((to, from, next)=> {
    console.log('to =>', to); //to가 현재임을 알 수 있다
    console.log('from =>', from);

    //로그인, 로그아웃은 url 저장하지 않고 제외, 나머지는 url은 모두저장
    // 로그인 로그아웃은 되돌아갈 페이지가 아니기 때문에
    if(to.path !== '/login' && to.path !== '/logout'){ 
        sessionStorage.setItem("CURR_URL", to.path);

        // object => string으로 변경 = JSON.stringify(변경할 object)
        // string => object으로 변경 = JSON.parse(변경할 문자)
        sessionStorage.setItem("CURR_QRY", JSON.stringify(to.query));
    }
    next();
})  
    

export default router;

main.js에 생성된 라우트파일 등록

📁vue/fd_restaurant/src/main.js

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

import routes from './routes/index';

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

App.vue 라우터설정

📁vue/fd_restaurant/src/App.vue

<template>
  <div class="box">
    <h3>메인화면</h3>
    <router-link to='/login'><button>로그인</button></router-link>
    <router-link to='/insert'><button>등록하기</button></router-link>
  </div>


  <router-view></router-view>
</template>

<script>


export default {
  
}
</script>

<style>
.box{
    width: 800px;
    border: 5px double skyblue;
    padding: auto;
    margin: auto;
}
</style>

restaurant 등록(가입) 페이지

📁vue/fd_restaurant/src/components/restaurant/insertpage.vue

<template>
    <div class="box">
        <h3>가게등록</h3>
        <div>
            <label class="lbl">사업자번호</label>
            <input type="text" style="border: 1px solid #cccccc; width:300px"  v-model="state._id"/>
            <label>중복확인</label>
        </div>
        <div>
            <label class="lbl">암호</label>
            <input type="text" style="border: 1px solid #cccccc; width:300px" v-model="state.password" />
        </div>
        <div>
            <label class="lbl">암호확인</label>
            <input type="text" style="border: 1px solid #cccccc; width:300px"  v-model="state.password1"/>
        </div>
        <div>
            <label class="lbl">상호명</label>
            <input type="text" style="border: 1px solid #cccccc; width:300px"  v-model="state.name"/>
        </div>
        <div>
            <label class="lbl">연락처</label>
            <input type="text" style="border: 1px solid #cccccc; width:300px" v-model="state.phone" />
        </div>
        <div>
            <label class="lbl">주소</label>
            <input type="text" style="border: 1px solid #cccccc; width:300px"  v-model="state.address"/>
        </div>
        <div>
            <label class="lbl">카테고리코드</label>
            <select v-model="state.categorycode">
                <option v-for="tmp of state.rows" :key="tmp" :value="tmp._id">{{tmp.content}}</option>
            </select>
        </div>
        <br />
        <hr style="border: 1px solid skyblue" />
        <button @click="handleJoin">가입하기</button>

    </div>
</template>

<script>
import axios from 'axios';
import { onMounted, reactive } from '@vue/runtime-core';
import { useRouter } from 'vue-router';
export default {
    setup () {
        const router = useRouter();

        const state = reactive({
            rows : [],
            _id : "000-00-0000", 
            password : "0000",
            password1 : "0000",
            name : "파전", 
            phone : "010-9999-9999", 
            address : "경기", 
            categorycode : "", 

        })

        // 카테고리 코드 가져오기
        const handleData = async() => {
            const url = `/api/fd_category/select.json`;
            const headers = {"Content-Type":"application/json"};
            const { data } = await axios.get(url, {headers});
            // console.log(data); // => [{…}, {…}, {…}, {…}, {…}]
            
            if(data.status === 200){
                state.rows = data.rows;
            }
            console.log('state.rows=>',state.rows)
        };

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

        const handleJoin = async() => {
            const url = `/api/fd_restaurant/insert.json`;
            const headers = {"Content-Type":"application/json"};
            const body = {
                _id : state._id, 
                password : state.password,
                name : state.name,
                phone : state.phone, 
                address : state.address, 
                categorycode : state.categorycode, 
            }
            const { data } = await axios.post(url, body, {headers});
            console.log(data);
            if(data.status === 200){
                alert('로그인되었습니다. 관리페이지로 이동합니다');
                router.push({path:'/'})
            }
        }
        

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

<style lang="css" scoped>
.box{
    width: 800px;
    border: 5px double skyblue;
    padding: auto;
    margin: auto;
}

.lbl {
    display: inline-block;
    width:130px
}
</style>

DB에 저장된 카테고리 목록 가져오기

  1. handleData 함수 실행
    ➡️ 데이터 확인 console.log(data)
  2. state.rows = data.rows; 담아두기
  3. select 태그에 v-model 걸어주기
  4. option 태그에 값 지정하기
    • v-for
    • :key
    • :value ➡️ v-model에 보낼 값
    • {{tmp.들어갈내용}}
 <div>
            <label class="lbl">카테고리코드</label>
            <select v-model="state.categorycode">
                <option v-for="tmp of state.rows" :key="tmp" :value="tmp._id">{{tmp.content}}</option>
            </select>
        </div>

restaurant 등록하기

  1. handleJoin 함수생성
  2. state 변수생성
  3. 데이터를 가져올 tag에 v-model 지정
  4. 결과값 확인 후 이동
if (data.status === 200) {
                alert('회원가입이 완료되었습니다!');
                router.push({ path: '/' });
            }

0개의 댓글