おもちゃプロジェクト

개인 블로그 만들기(4)

차가리 2022. 3. 30. 14:45
728x90

과정

글을 안올리는 동안 했던 프로젝트 과정을 적을려고 한다.

Mongoose Model 분리

저번 글에서는 스키마를 생성해서 모델을 생성 후 모델 안에다가 데이터 처리하는 로직을 넣었었다.

분리하는게 낫겠다고 판단하여 Controller 디렉토리를 만들어서 데이터 처리 함수를 넣어 놓는 목적으로 분리를 했다.

수정된 model

**models/admin-category.js

const mongoose = require('mongoose')

const { Schema } = mongoose

const admin_sub_categorySchema = new Schema({
    name : String,
    router_path : String
})

const admin_categorySchema = new Schema({
    name : String,
    router_path : String,
    children: [admin_sub_categorySchema]
});

const admin_category = mongoose.model('AdminCategory',admin_categorySchema)


module.exports = admin_category

카테고리를 대분류 소분류로 나누었기 때문에 서브 카테고리라는 스키마를 메인 카테고리의 children에 넣었다.
이런 방식은 데이터의 변동이 많으면 추천 하지 않은 방식이지만 카테고리는 고정으로 둘 것이기 때문에 이렇게
만들었다.

Controller 디렉토리 생성

프로젝트의 루트 경로에다가 만들어 놓는다.

먼저 admin page에 사용할 카테고리를 DB에 저장해서 가져오는 방식으로 했다.

**controller/admin-category.js

const AdminCategory = require('../models/admin-category');


module.exports ={

    async getCategory () {

        return AdminCategory.find({},{_id:0,__v:0}).sort({_id:1})

    },
    async createCategory (payload) {

        const category = new AdminCategory({
            name : payload.name,
            router_path: payload.router_path,
            children : []
        });
        return await category.save();
    },
    async createSubCategory(payload) {
        const name = payload.name
        const router_path = payload.router_path
        const id = payload.adminCategoryId

        const params = {name:name,router_path:router_path}
        const category = await AdminCategory.findById({_id:id}).exec()
        if(category){
            category.children.push(params)
            category.markModified('children')
          return  category.save().then(result=>{
                console.log('success')
            }).catch(err=>{
                console.log(err)
            })
        }
    }
}

여기서 중요하게 봐야 할 것은 async await도 있지만 아직 나도 공부중이기 때문에 나중에 따로 글을 작성하도록 하겠다.

일단 메인 카테고리를 생성하면 chindren에 값을 안넣으면 해당 도큐먼트가 사라진 채로 들어가기 때문에 빈 배열을 넣었다.

그리고 밑에 createSubCategory 함수 부분에 있는 .push()는 새롭게 값을 넣는다는 함수이다.

markModified는 업데이트하려는 배열 열을 수정된 것으로 수동으로 설정하여 mongoose가 열 변경을 감지하고 DB를 업데이트하게 해준다.

해당 관련 글은 여기서 확인해보면 된다.

https://sarav.co/understanding-markModified-in-mongoose

**routes 설정

이제 controller를 추가함으로 써 routes 부분도 바껴야한다.

**routes/admin.js

const admin_category =require('../controller/admin-category')
const router = require('express').Router();





router.get('/',(req,res)=>{
        admin_category.getCategory()
            .then((result)=>{
                if(!result) return res.status(204).send('No Category');
                return res.status(200).json({categories:result})
            }).catch(err=>{
                res.status(500).send(err);
        })
})

router.post('/create',(req,res)=>{
    // Board.create(req.body).then(()=>{}).catch(err=>res.status(500).send(err));
        admin_category.createCategory(req.body.params)
            .then(() => {
                res.status(200).send('success');
            }).catch(err => {
                console.log(err);
        })
    // console.log(req.body.params.name);
})

router.post('/sub-category-create',(req,res)=>{

    admin_category.createSubCategory(req.body.params)
        .then(()=>{
            res.status(200).send('success');
        }).catch(err=>{
            console.log(err);
    })

})

module.exports = router;

바뀐점은 controller를 require 해서 controller에 있는 함수를 호출해서 사용하면 된다.

Admin Page 생성

front 에서는 Admin Page를 추가 했다.

AdminPage가 될 뼈대인 AdminLayout.vue 를 생성했다.

AdminLayout.vue

<template>
  <q-layout view="hhh lpr fff">
    <admin-header/>
    <q-page-container>
      <admin-drawer-right/>
      <router-view />
    </q-page-container>
  </q-layout>
</template>

<script>
import { computed, onBeforeMount, reactive } from 'vue'
import AdminHeader from '../../components/default/Header'
import AdminDrawerRight from "components/body/admin/AdminDrawerLeft";
export default {
  name: "Admin",
  components:{
    AdminDrawerRight,
    AdminHeader
  },
  setup() {

    return {

    }
  }
}
</script>

<style scoped>

</style>

그리고 /admin에서 루트 경로로 들어올 때 보여줄 첫 화면을 생성한다.

AdminDefaultPage

<template>
<div>
  <div class="row justify-center q-ma-md">
      <q-card
      class="col-4"
      flat
      bordered
      >
       <div class="text-center">
         <h6 class="no-margin">Today Visitor</h6>
         <p class="text-subtitle1">10</p>
       </div>
      </q-card>
      <q-card
      class="col-4"
      flat
      bordered
      >
        <div class="text-center">
          <h6 class="no-margin">YesterDay Visitor</h6>
          <p class="text-subtitle1">10</p>
        </div>
      </q-card>
      <q-card
      class="col-4"
      flat
      bordered
      >
        <div class="text-center">
          <h6 class="no-margin">Total Visitor</h6>
          <p class="text-subtitle1">10</p>
        </div>
      </q-card>
  </div>
  <div class="row justify-center q-ma-md">
      <q-card
        class="col"
        flat
        bordered
      >
        <apexchart
          type="line"
          height="350"
          :options="state.options"
          :series="state.series"
        />
      </q-card>
  </div>
  <div class="row justify-center q-ma-md">
    <q-card>
      <!-- 인기글 들어가는 곳 -->
    </q-card>
  </div>
  <div class="row justify-center q-ma-md">
    <q-card>
      <!-- 최근 글 들어가는 곳(옆으로) -->
    </q-card>
  </div>
</div>
<!--

  들어가야 될것들

  오늘 방문자수

  차트(방문자수)

  최근 게시물

  인기 글 (최대 5개만)

-->
</template>
<script>
import {computed, onBeforeMount, reactive} from "vue";
import {useRoute, useRouter} from 'vue-router';

export default {
  name : 'AdminDefaultPage',

  setup() {

    const router = useRouter()
    const routes = useRoute()
    const state = reactive({
      options: {
        chart: {
          id: 'vuechart-example'
        },
        xaxis: {
          datetimeFormatter: {
            year: 'yyyy',
            month: 'MMM \'yy',
            day: 'dd MMM',
            hour: 'HH:mm'
          }
        }
      },
      series:[{
        name: 'series-1',
        data:[30,40,45,50,49,60,70,91]
      }]

    })
    onBeforeMount(()=>{
      const category = routes.params.category
      if(category == null){

      }
    })
    return {
      state
    }
  }
}
</script>
<style>

</style>

아직 제작 중이라 빈 곳이 많다.

는 외부 컴포넌트 이다. 일일 방문자 수 등을 차트로 보여주기 위해서 사용했다.

이제 페이지를 만들었으니 라우터 설정을 해줘야 한다.

router 수정

export default [
  {
    path: '/admin',
    name: 'Admin',
    component: () => import('layouts/admin/AdminLayout'),
    children: [
       {
         path: '',
         component: () => import('pages/admin/AdminDefaultPage')
       }
    ]
  }
]

현재까지 변경 사항은 이렇다.

번외

코드를 관리하기 위해서 우리는 github에다가 올려놓고 풀, 푸쉬, 커밋 등을 한다. 하지만 깃헙에 올려놓는 것은 public으로

되있으므로(private은 모르겠다.) 민감한 정보 등은 숨겨 놓는게 좋다. (db 계정정보 등...)

.env 파일로 환경변수처럼 변수 안에다가 정보등을 넣어놓고 필요할 때 사용하는게 낫다.

그러기 위해서 필요한 것은 dotenv이다.

npm install dotenv --save

설치 후 루트 경로에다가 .env 파일을 만든다.

**.env 파일

DB_URL=mongodb://<계정>:<password>@localhost:27017/blog

후에 db connection을 하는 곳으로 가서 적용하면된다.

**db.js

//DB Connection 
const mongoose = require('mongoose');
require('dotenv').config();
 module.exports = () => { 
     function connect() { 
         mongoose.connect(process.env.DB_URL,
         function(err) { // .connect is db connection 
            if(err) { 
                console.log('mongodb connection error : ', err);
             } 
             console.log('mongodb connected'); 
            }) }
             connect();
             mongoose.connection.on('disconnected',connect);
             }

require('dotenv').config() 를 추가해주고 process.env.설정한 변수명으로 하면 된다.

그리고 깃허브에 .env를 올리면 않되므로 .gitignore가 있으면 수정해주고 없으면 루트 경로에 생성 후 .env 파일을 적어주면 된다.

**.gitignore

.env
728x90