본문 바로가기

페이팔기반, e커머스 플랫폼 제작 [5편. 전역객체 page구현하기 ]

by Recstasy 2021. 11. 8.

페이지는 홈의 상단부에 배치된 주요 메뉴이다. 지난 포스팅 3편에서는 관리자 라우팅('/admin/pages')에서 페이지를 관리하는 기능을 구현했다. 이번 포스팅에서는 일반 사용자가 홈에서 볼 수 있는 페이지를 구현해보자.  

 

 

 

 


1 index.js

page데이터는 관리자 뿐 아니라 웹 사이트에 접속하는 모두가 볼 수 있어야 한다. 이를 위해서는 page모델의 데이터를 받아서 어디에서든 접근할 수 있는 app.locals.pages객체가 필요하다. app.locas.pages객체는 전역객체이므로 index.js에 선언한다. 

 


  //중략...

 
  //Get page Model

    let Page = require('./models/pageSchema');

  //Get all pages to pass to header.ejs
    Page.find({}).sort({sorting:1}).exec((err, pages)=>{
        if(err){
            console.log(err);
        } else{
            app.locals.pages = pages;
        }
    });

  //중략...

[ index.js]

 

 

 

 

 

 


2 ejs :: header.ejs

관리자 페이지에서 page를 수정하거나 추가할 때마다 메인 화면이 자동으로 바뀌려면, header.ejs의 nav리스트가 조건문에 따라서 랜더링되어야 한다. 이를 위해 header.ejs를 아래와 같이 수정한다.

 


  <!doctype html>

  <!-- 중략... -->

        <div id="navbar" class="collapse navbar-collapse">
            <ul class="nav navbar-nav">
            <% pages.forEach((page)=>{ %>
                <% if(page.slug == "home"){ %>
                    <li><a href="/"><%= page.title %></a></li>
                <% }else{ %>
                    <li><a href="/<%= page.slug %>"><%= page.title %></a></li>
                <% } %>
            <% }) %>
            </ul>
        </div><!--/.nav-collapse -->
        </div>
    </nav>


    <div class="container">
    <%- messages('messages', locals) %>

[ header.ejs ]

 

 

 

 

 

 

 

 


3 관리자 페이지 순서변경 구현

현재 아래와 같이 관리자는 관리자 페이지에서 페이지 순서를 마음대로 변경할 수 있으며, 지난 포스팅(2편)에서 구현했다.

 

 

관리자가 변경한 페이지의 순서가 관리자 홈 뿐만 아니라 일반 사용자의 홈에서도 변경이 반영되려면, 전역 변수와 콜백의 조합이 필요하다. 아래의 코드는 이를 반영했으며, sortPages함수는 관리자가 변경한 페이지의 순서를 실시간으로 index.js에 있는 req.locas전역 객체에 전달한다. 

 


  //중략...

  //Sort pages functions

    function sortPages(ids,cb){
        let count = 0;

        for(let i=0; i<ids.length; i++){
            let id = ids[i];
            count++;

            ((count)=>{
                Page.findById(id, (err,page)=>{
                    page.sorting = count;
                    page.save((err)=>{
                        if(err) return console.log(err);
                        ++count;
                        if(count >= ids.length){
                            cb();
                        }
                    })
                })
            })(count);
        }
    }


  //Post reorder pages :: 지난 포스팅 2편에서 구현한 부분을 수정하기
    router.post('/reorder-pages', (req, res)=>{
        let ids = req.body['id[]'];

        sortPages(ids, ()=>{
            Page.find({}).sort({sorting:1}).exec((err, pages)=>{
                if(err){
                    console.log(err);
                } else{
                    req.app.locals.pages = pages;
                }
            });
        })
    });

[ admin_pages.js ]

 

 

sort({sorting:1})부분은 오름차순으로 정리하라는 의미이며, exec()는 콜백으로 다음 코드를 실행한다. page추가할 때도 변경된 부분이 req.app.locas.pages에 저장되어야 한다.

 


  //Post add page
    router.post('/add-page', async(req, res)=>{
    
        await check('title', 'title must have a value.').notEmpty().run(req);
        await check('content', 'Content must have a value.').notEmpty().run(req);

        let title = req.body.title;
        let slug = req.body.slug.replace(/\s+/g, '-').toLowerCase();
        if(slug == "") slug = title.replace(/\s+/g, '-').toLowerCase();
        let content = req.body.content;

  // 중략...

                 page.save((err)=>{
                     if(err){
                         return console.log(err);
                     }

                     Page.find({}).sort({sorting:1}).exec((err, pages)=>{
                         if(err){
                             console.log(err);
                         } else{
                             req.app.locals.pages = pages;
                         }
                     });

                        req.flash('sucess', 'Page added!');
                        res.redirect('/admin/pages');
                    });
                }
            });
        }
    });


[ admin_page.js ]

 

 

삭제 역시 업데이트가 진행된다.

 


  //Get delete page

    router.get('/delete-page/:id', (req, res)=>{
        Page.findByIdAndRemove(req.params.id, (err)=>{
            if(err) return console.log(err);

            Page.find({}).sort({sorting:1}).exec((err, pages)=>{
                if(err){
                    console.log(err);
                } else{
                    req.app.locals.pages = pages;
                }
            });

            req.flash('success', 'Page Deleted');
            res.redirect('/admin/pages/')
        })
    });

[ admin_page.js ]

 

 

수정도 같은 방식으로 해당 부분을 추가한다.

 

  //Post edit page
    router.post('/edit-page/:id', async(req, res)=>{
         await check('title', 'title must have a value.').notEmpty().run(req);
         await check('content', 'Content must have a value.').notEmpty().run(req);

        let title = req.body.title;
        let slug = req.body.slug.replace(/\s+/g, '-').toLowerCase();
        if(slug == "") slug = title.replace(/\s+/g, '-').toLowerCase();
        let content = req.body.content;
        let id = req.params.id;

  // 중략...

              Page.findById(id, (err,page)=>{
                  if(err) return console.log(err);
                  page.title = title;
                  page.slug = slug;
                  page.content = content;

                  page.save((err)=>{
                      if(err){
                          return console.log(err);
                      }

                      Page.find({}).sort({sorting:1}).exec((err, pages)=>{
                          if(err){
                               console.log(err);
                          } else{
                              req.app.locals.pages = pages;
                          }
                      });

                           req.flash('sucess', 'Page added!');
                           res.redirect('/admin/pages/edit-page/'+ id);
                       });
                   })

                }
            });
        }
    });

[ admin_page.js ]

 

 

 

 

 

 


4 메인 페이지

현재 상단에 위치한 각각의 페이지는 'index.ejs'파일로 모두 랜더링되고 있다. 테스트 중이므로 해당 라우터만 뚫어준다.

 


    let express = require('express');
    let router = express.Router();
    let Page = require('../models/pageSchema');
\
  // Get
    router.get('/', (req, res)=>{
        Page.findOne({slug:'home'}, (err, page)=>{
            if(err) console.log(err);

            res.render('index', {
                title : page.title,
                content : page.content
            })
        })
    });


  // Get a page
    router.get('/:slug', (req,res)=>{
        let slug = req.params.slug;
        Page.findOne({slug:slug}, (err, page)=>{
            if(err) console.log(err);
            if(!page){
                res.redirect('/');
            }else{
                res.render('index', {
                    title : page.title,
                    content : page.content
                })
            }
        })
    })

  //Exports
    module.exports = router;

[ pages.js ]

 

 

router.get('/:slug') 라우터는 페이지에 따라 해당 .ejs파일을 랜더링한다. 관련 페이지가 있다면 각각 해당되는 .ejs파일을 res.render('index')위치에 넣어준다. 위의 코드에서는 index.ejs로 통일하고, title, content를 다르게 전달하고 있다. index.ejs파일은 아래와 같이 아주 간단하다.

 


<%- include('./layouts/header.ejs') %>


<%- content %>


<%- include('./layouts/footer.ejs') %>

[ index.ejs ]

 

 

 

 

 

 


5 정리

 

페이지와 마찬가지로 일반 유저를 위한 카테고리가 필요하다. 게스트로 방문한 사용자는 메인 홈에서 자신이 원하는 카테고리를  선택할 수 있어야하며, 이를 위한 구현은 페이지와 같다.(전역객체, app.locals ) 다음 포스팅에서는 전역객체를 이용한 카테고리 접근을 풀어보자.

댓글

최신글 전체

이미지
제목
글쓴이
등록일