본문 바로가기
ICIA 수업일지

2021.08.10 수업일지(node.js, mysql)

by 주성씨 2021. 8. 10.

- 쇼핑몰 관리자 화면 만들기

C:\data\node\ex06\app.js

// 2021.08.10
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
app.use('/', indexRouter);
app.use('/users', usersRouter);

 

C:\data\node\ex06\views\index.ejs

<!DOCTYPE html>
<html>

<head>
  <title><%= title %></title>
  <link rel='stylesheet' href='/stylesheets/style.css' />
</head>

<body>
  <div id="container">
    <div id="header">
      <h2>쇼핑몰 관리자 화면</h2>
    </div>
    <div id="menu">
      <div class="item">공지사항</div>
      <div class="item">게시판관리</div>
      <div class="item">상품관리</div>
      <div class="item">회원관리</div>
    </div>
    <div id="content">
    </div>
    <div id="footer">
      <h3>Copyright. 오늘의 PJ는?</h3>
    </div>
  </div>
</body>

</html>

 

C:\data\node\ex06\public\stylesheets\style.css

@font-face {
  font-family: 'GmarketSansMedium';
  src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2001@1.1/GmarketSansMedium.woff') format('woff');
  font-weight: normal;
  font-style: normal;
}

body {
  font-family: 'GmarketSansMedium';
}

#container {
  border: 1px solid rgb(233, 124, 233);
  padding: 20px;
  width: 960px;
  margin: 0px auto;
}

#header {
  border: 1px solid rgb(233, 124, 233);
  padding: 10px;
  margin-bottom: 10px;
}

h2, h3 {
  text-align: center;
  color: rgb(86, 16, 86);
}

#menu {
  border: 1px solid rgb(233, 124, 233);
  padding: 20px;
  margin-bottom: 10px;
  overflow: hidden;
}

#menu .item {
  float: left;
  width: 100px;
  background-color: rgb(194, 36, 194);
  color: white;
  padding: 5px;
  margin-left: 10px;
  text-align: center;
  cursor: pointer;
}

#menu .item:hover{
  background-color: white;
  color: purple;
}

#content {
  border: 1px solid rgb(233, 124, 233);
  padding: 20px;
  margin-bottom: 10px;
}

#footer {
  border: 1px solid rgb(233, 124, 233);
  padding: 20px;
}

 

 

- views에 새로운 .ejs를 만든다. 출력되는 파일은 views에 만든다.

[new] C:\data\node\ex06\views\info.ejs

<h3>쇼핑몰 소개</h3>
<p>돋고, 날카로우나 커다란 사랑의 바로 것이다. 안고, 투명하되 생의 위하여서 더운지라 것이다. 주는 그들의 얼마나 그것을 심장의 같이, 그들의 만천하의 봄바람이다. 있을 희망의 부패를 눈이 사람은 힘있다.
    커다란 끝까지 뭇 없으면 귀는 어디 구하지 굳세게 이상 보라. 거친 청춘의 그것을 갑 살 청춘은 미묘한 위하여 없으면 아니다. 그들의 기관과 피에 칼이다. 남는 생명을 천하를 것은 소담스러운 그리하였는가?
    설산에서 하는 어디 튼튼하며, 황금시대를 끓는 있음으로써 거선의 봄바람이다. 발휘하기 같이, 얼음 사랑의 인생을 품에 튼튼하며, 것이다.</p>
<p>많이 대중을 생생하며, 그와 가진 기관과 청춘의 끓는 미인을 철환하였는가? 구하지 오직 그들의 피가 천자만홍이 생명을 운다. 풀이 사랑의 불어 구하지 과실이 것이 석가는 약동하다. 내는 곧 현저하게 칼이다.
    평화스러운 인간이 모래뿐일 듣는다. 끓는 뜨고, 피어나기 것이다. 기쁘며, 창공에 몸이 열매를 교향악이다. 있는 스며들어 품으며, 그림자는 인도하겠다는 보는 사는가 가치를 힘있다. 긴지라 방황하여도, 피어나기
    풀이 옷을 품었기 가슴에 이것이다. 얼음에 물방아 원대하고, 가치를 맺어, 때문이다.</p>
<p>황금시대를 있으며, 튼튼하며, 눈이 커다란 청춘의 천자만홍이 이상이 힘있다. 많이 앞이 일월과 힘차게 살 웅대한 용감하고 이상의 사막이다. 수 새가 얼음에 굳세게 없으면 천지는 곳으로 일월과 끓는 이것이다.
    열락의 따뜻한 수 노년에게서 사막이다. 우리는 우리의 그들은 것이다.보라, 그들의 방황하였으며, 피부가 아니다. 있으며, 남는 구하지 피는 피에 우리는 곳으로 사막이다. 창공에 군영과 따뜻한 밝은 영락과
    가치를 갑 두손을 듣는다. 우는 트고, 기관과 찾아 시들어 같으며, 품었기 생의 운다. 불어 황금시대를 풀이 그것을 그러므로 그들의 가슴에 바이며, 그들은 것이다. 생의 우리의 우리 맺어, 길지 얼마나
    말이다. 남는 끓는 굳세게 가는 갑 어디 힘차게 없으면 그들의 그리하였는가?</p>

 

C:\data\node\ex06\views\index.ejs

    <div id="content">
      <%-include('info.ejs')%>
    </div>

 

 

C:\data\node\ex06\routes\index.js

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

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Lalla Roola', pageName: 'info.ejs' }); //index.ejs를 render
});

module.exports = router;

 

C:\data\node\ex06\views\index.ejs

pageName에 info.ejs를 넣어 아래와 같이 쓸 수 있다.

    <div id="content">
      <%-include(pageName)%>
    </div>

 

- 공지사항, 게시판관리, 상품관리, 회원관리를 위한 라우터를 만든다.

C:\data\node\ex06\app.js

// 2021.08.10
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var noticeRouter = require('./routes/notice'); // new
var bbsRouter = require('./routes/bbs'); // new
var productRouter = require('./routes/product'); // new
var memberRouter = require('./routes/member'); // new
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/notice', noticeRouter); // new
app.use('/bbs', bbsRouter); // new
app.use('/product', productRouter); // new
app.use('/member', memberRouter); // new

 

[new] C:\data\node\ex06\routes\notice.js

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

/* GET 공지사항. */
router.get('/', function(req, res, next) {
  res.render('index',{title:'공지사항', pageName:'notice.ejs'});
});

module.exports = router;

 

[new] C:\data\node\ex06\routes\bbs.js

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

/* GET 공지사항. */
router.get('/', function(req, res, next) {
  res.render('index',{title:'게시판관리', pageName:'bbs.ejs'});
});

module.exports = router;

 

[new] C:\data\node\ex06\routes\product.js

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

/* GET 공지사항. */
router.get('/', function(req, res, next) {
  res.render('index',{title:'상품관리', pageName:'product.ejs'});
});

module.exports = router;

 

[new] C:\data\node\ex06\routes\member.js

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

/* GET 공지사항. */
router.get('/', function(req, res, next) {
  res.render('index',{title:'회원관리', pageName:'member.ejs'});
});

module.exports = router;

 

[new] C:\data\node\ex06\views\notice.ejs

<h3>공지사항</h3>

[new] C:\data\node\ex06\views\bbs.ejs

<h3>게시판 관리</h3>

[new] C:\data\node\ex06\views\product.ejs

<h3>상품관리</h3>

[new] C:\data\node\ex06\views\member.ejs

<h3>회원관리</h3>

 

C:\data\node\ex06\views\index.ejs

<body>
  <div id="container">
    <div id="header"><a href="/">
      <h2>쇼핑몰 관리자 화면</h2></a>
    </div>
    <div id="menu">
      <a href="/notice"><div class="item">공지사항</div></a>
      <a href="/bbs"><div class="item">게시판관리</div></a>
      <a href="/product"><div class="item">상품관리</div></a>
      <a href="/member"><div class="item">회원관리</div></a>
    </div>
    <div id="content">
      <%-include(pageName)%>
    </div>
    <div id="footer">
      <h3>Copyright. Lalla Roola. All rights reserved.</h3>
    </div>
  </div>
</body>

 

 

 

- back to mysql

- root로

#2021.08.10
#데이터 베이스 생성
create database shoppingdb;
#유저 생성
create user 'shopping'@'localhost' identified by 'pass';
#유저에게 데이터베이스 권한 부여
grant all privileges on shoppingdb.* to 'shopping'@'localhost';

 

- shoppingdb open

create table notice(
   no int auto_increment primary key,
    title varchar(200) not null,
    content varchar(2000),
    wdate datetime default now()
);

insert into notice(title, content)
values('안녕하세요 카카오입니다.','카카오 서비스를 이용해 주시는 회원 여러분께 감사드립니다.위치정보관리책임자 변경에 대해 안내드리기 위하여, 카카오 서비스 약관의 내용이 2021년 8월 9일자로 변경될 예정임을 안내드립니다.');
insert into notice(title, content)
values('위치기반서비스 이용약관 변경 안내','안녕하세요.카카오의 서비스를 이용해주시는 회원 여러분께 감사드리며, 위치기반서비스 이용약관 변경에 관한 안내 말씀 드립니다.');
insert into notice(title, content)
values('카카오 통합서비스약관, 카카오 서비스 약관, 카카오 통합 약관, 카카오 운영정책 변경 안내','안녕하세요 카카오입니다.카카오 서비스를 이용해 주시는 회원 여러분께 감사드립니다.카카오 통합서비스약관, 카카오 서비스 약관, 카카오 통합 약관, 카카오 운영정책의 내용이 2021년 7월 1일자로 변경될 예정임을 안내드립니다.분사로 인하여 카카오톡 채널의 카카오알림 카테고리에서 "멜론" 은 제외될 예정입니다.다만, 분사 이전에 카카오알림 채널 추가 및 광고메시지 수신에 동의하여 "멜론" 채널이 이미 추가된 경우에는 계속 유지됩니다. ');
insert into notice(title, content)
values('개인정보 처리방침 개정안내','안녕하세요. 카카오(이하 ‘회사’)입니다.서비스를 이용해 주시는 이용자 여러분께 감사드리며, 새로운 개인정보 처리방침 적용에 관한 안내 말씀 드립니다회사는 이용자 여러분의 개인정보를 무엇보다 소중하게 처리하고 있으며, 어떤 사안보다도 우선하여 안전하게 관리하고 있습니다.새롭게 변경될 개인정보 처리방침 내용을 확인하시고 서비스 이용에 참고하시기 바랍니다.');
insert into notice(title, content)
values('카카오 전자금융거래 이용약관 변경 사전 안내',' 변경 사전 안내 2019-10-25 안녕하세요. 카카오입니다.카카오 서비스를 이용해주시는 회원 여러분께 감사드립니다.건전한 상거래 환경 조성 및 고객의 안전한 결제서비스 이용을 위해 카카오 전자금융거래 이용약관의 내용이 2019년 12월 1일자로 변경될 예정입니다. ');

select * from notice;

 

- back to VSC

- 공지사항 DB에서 가져오기

[new] C:\data\node\ex06\db.js

var mysql = require('mysql');
var conn;
exports.connect = function () {
    conn = mysql.createPool({
        connectionLimit: 100,
        host: 'localhost',
        user: 'shopping',
        password: 'pass',
        database: 'shoppingdb'
    });
}
exports.get = function () {
    return conn;
};

connect는 app.js에서

 

C:\data\node\ex06\app.js

//2021.08.10
//데이타베이스 연결
var db = require('./db');
db.connect(function(err){
  if(err){
    console.log('DB error.......');
    process.exit(1);
  }else{
    console.log('DB Success......');
  }
});

 

C:\data\node\ex06\routes\notice.js

var express = require('express');
var router = express.Router();
var db = require('../db.js');

/* GET 공지사항 title, pageName. */
router.get('/', function(req, res, next) {
  res.render('index',{title:'공지사항', pageName:'notice.ejs'});
});

/* GET 공지사항 to DB. */ // new
// '/'는 이미 위에서 사용했기때문에 아래와 같이 한다.
router.get('/notice.json', function(req, res, next) {
 var sql = 'select * from notice order by no desc';
 db.get().query(sql,[],function(err,rows){
   res.send(rows);
 });
});

module.exports = router;

 

 

- 이제 DB 내용을 출력해보자.

C:\data\node\ex06\views\index.ejs

<head>
  <title><%= title %></title>
  <link rel='stylesheet' href='/stylesheets/style.css' />
  <script src="http://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>

 

C:\data\node\ex06\views\notice.ejs

- 여기서 출력해줘야 한다.

<h3>공지사항</h3>
<a href=""></a>
<style>
    #tbl .row {
        border-bottom: 1px solid green;
        margin-bottom: 10px;
        cursor: pointer;
        padding: 10px;
    }

    #tbl .row:hover {
        background-color: lemonchiffon;
    }

    #tbl .title {
        display: inline-block;
        width: 700px;
    }

    #tbl .content {
        margin: 20px 0px 20px 0px;
        background-color: rgb(226, 255, 226);
        padding: 20px;
    }
</style>
<table id="tbl"></table>

<script>
    getList();
    function getList() {
        $.ajax({
            type: 'get',
            url: '/notice/notice.json',
            dataType: 'json',
            success: function (data) {
                var str = '';
                $(data).each(function () {
                    var no = this.no;
                    var title = this.title;
                    var date = this.fdate;
                    str += `<tr class="row">`;
                    str += `<td class="no">${no}</td>`;
                    str += `<td><div class="title">${title}</div></td>`;
                    str += `<td class="date">${date}</td>`;
                    str += `</tr>`;
                });
                $('#tbl').html(str);
            }
        });
    };
</script>

 

- 공지사항 입력 페이지 추가

C:\data\node\ex06\routes\notice.js

var express = require('express');
var router = express.Router();
var db = require('../db.js');

/* GET 공지사항 title, pageName. */
router.get('/', function(req, res, next) {
  res.render('index',{title:'공지사항', pageName:'notice.ejs'});
});

/* GET 공지사항목록*/
router.get('/notice.json', function(req, res){
  var sql ='select *,date_format(wdate,"%Y-%m-%d %h:%i:%s") fdate from notice order by no desc';
  db.get().query(sql, [], function(err, rows){
    res.send(rows);
  });
});

/* GET 공지사항입력 */
router.get('/insert', function(req, res){
  res.render('index', {title:'공지사항입력', pageName:'notice_insert.ejs'});
});

module.exports = router;

 

C:\data\node\ex06\views\notice.ejs

<h3>공지사항</h3>
<a href="/notice/insert" style="margin-left: 30px;">글쓰기</a> // new
<table id="tbl"></table>

 

[new] C:\data\node\ex06\views\notice_insert.ejs

<h3>공지사항입력</h3>

 

 

 

- 공지사항을 입력할 form을 만들어보자. 데이터를 입력해보자.

C:\data\node\ex06\views\notice_insert.ejs

<style>
    table{
        width: 920px;
        margin: 0px auto;
        padding: 10px;
        background-color: rgb(247, 212, 247);
    }
    #groupButton{
        width: 920px;
        text-align: center;
        margin-top: 15px;
    }
    input, textarea{
        font-size: 15px;
    }
</style>
<h3>공지사항입력</h3>
<!-- 양식 테그는 form -->
<form name="frm">
    <table>
        <tr>
            <td><input type="text" name="title" placeholder="제목을 입력하세요." size="110" style="padding: 5px;"></td>
        </tr>
        <tr>
            <td><textarea name="content" placeholder="내용을 입력하세요." rows="15" cols="112" style="padding: 5px;"></textarea></td>
        </tr>
    </table>
    <div id="groupButton">
        <input type="submit" value="등록"/>
        <input type="reset" value="취소"/>
    </div>
</form>

 

- 동적 스크립트를 추가해준다.

<script>
    // submit은 무조건 되므로 e를 넣는다.
    // name은 .이나 #을 안붙여도 된다.
    $(frm).on('submit',function(e){
        e.preventDefault(); // submit을 박는다.
        var title=$(frm.title).val();
        if(title===''){
            alert("제목을 입력하세요.");
            $(frm.title).focus();
            return;
        };
        var content=$(frm.content).val();
        if(content===''){
            alert("내용을 입력하세요.");
            $(frm.content).focus();
            return;
        };
        // !가 붙었으니 false면 return이 된다.
        if(!confirm('내용을 등록하시겠습니까?')) return;
    });
</script>

 

C:\data\node\ex06\routes\notice.js

/* POST 공지사항입력*/ // new
router.post('/insert',function(req,res){
  //post로 넘어오는 데이터는 body에 저장된다.
  var title=req.body.title;
  var content=req.body.content;
  var sql='insert into notice(title, content) values(?,?);';
  db.get().query(sql,[title, content],function(err,rows){
    res.sendStatus(200);
  });
});

https://minosaekki.tistory.com/44

 

Status Code(HTTP 상태 코드)란?

HTTP Status Code 란 간단하게 말하자면 클라이언트가 서버에게 요청을 보낼 때 그 요청의 결과가 어떻게 되었는지를 알려주는 것입니다. 이를 통해 요청을 했을 때 그 요청이 성공적인지 혹은 에러

minosaekki.tistory.com

 

C:\data\node\ex06\views\notice_insert.ejs

        // !가 붙었으니 false면 return이 된다.
        if(!confirm('내용을 등록하시겠습니까?')) return;

        // 내용을 insert 하는 작업 // new
        $.ajax({
            type:'post',
            url:'/notice/insert',
            data:{'title':title,'content':content},
            success: function(data){ // data 받을게 없으니
                alert('저장되었습니다.');
            }
        });
    });
</script>

 

- 공지사항 특정 데이터를 읽어보자.

C:\data\node\ex06\routes\notice.js

/* 공지사항 read*/
router.get('/read',function(req,res){
  var no = req.query.no;
  var sql = 'select * from notice where no=?;';
  db.get().query(sql,[no],function(err,rows){
    res.send(rows[0]);
  });
});

 

 

C:\data\node\ex06\routes\notice.js

/*GET 공지사항 Read*/
router.get('/read', function(req, res){
  var no=req.query.no;
  var sql='select * from notice where no=?';
  db.get().query(sql, [no], function(err, rows){
    res.render('index', {title: '공지사항 정보', pageName: 'notice_read.ejs', notice:rows[0]});
  });
});

 

[new] C:\data\node\ex06\views\notice_read.ejs

<h3>공지사항정보</h3>
<!-- 양식 테그는 form -->
<form name="frm">
    <table>
        <tr>
            <td><input type="text" name="title" value="<%=notice.title%>" size="100" style="padding: 5px;"></td>
        </tr>
        <tr>
            <td><textarea name="content" rows="15" cols="102" style="padding: 5px;"><%=notice.content%></textarea>
            </td>
        </tr>
    </table>
    <div id="groupButton">
        <input type="submit" value="등록" />
        <input type="reset" value="취소" />
    </div>
</form>

 

 

- 삭제 버튼을 통해서 삭제하기

C:\data\node\ex06\routes\notice.js

/*GET 공지사항 delete*/
router.get('/delete', function(req, res){
  var no=req.query.no;
  var sql='delete from notice where no=?;';
  db.get().query(sql, [no], function(err, rows){
    res.sendStatus(200);
  });
});

C:\data\node\ex06\views\notice_read.ejs

    <div id="groupButton">
        <input type="submit" value="수정" />
        <input type="reset" value="취소" />
        <input type="button" value="삭제" id="btnDelete"/>
    </div>
<script>
    // 삭제 버튼을 눌렀을때
    $('#btnDelete').on('click',function(){
        var no = "<%=notice.no%>"
        if(!confirm(no+' 을(를) 삭제하시겠습니까?')) return;
        $.ajax({
            type: 'get',
            url:'/notice/delete',
            data:{'no':no},
            success:function(data){
                alert('삭제되었습니다.');
                location.href='/notice';
            }
        });
    });

 

 

- 수정버튼을 통해 수정

C:\data\node\ex06\routes\notice.js

/*post 공지사항 update*/
router.get('/update', function(req, res){
  var no=req.body.no;
  var title=req.body.title;
  var content=req.body.content;
  var sql='update notice set title=?, content=? where no=?;';
  db.get().query(sql, [title, content, no], function(err, rows){
    res.sendStatus(200);
  });
});

 

C:\data\node\ex06\views\notice_read.ejs

<style>
    table {
        width: 700px;
        margin: 0px auto;
        padding: 10px;
        background-color: rgb(247, 212, 247);
    }

    #groupButton {
        width: 920px;
        text-align: center;
        margin-top: 15px;
    }

    input,
    textarea {
        font-size: 15px;
    }
</style>
<h3>공지사항정보</h3>
<!-- 양식 테그는 form -->
<form name="frm">
    <table>
        <tr>
            <td><input type="text" name="title" value="<%=notice.title%>" size="100" style="padding: 5px;"></td>
        </tr>
        <tr>
            <td><textarea name="content" rows="15" cols="102" style="padding: 5px;"><%=notice.content%></textarea>
            </td>
        </tr>
    </table>
    <div id="groupButton">
        <input type="submit" value="수정" />
        <input type="reset" value="취소" />
        <input type="button" value="삭제" id="btnDelete" />
    </div>
</form>
<script>
    // 전역변수로
    var no = "<%=notice.no%>"

    // 삭제 버튼을 눌렀을때
    $('#btnDelete').on('click', function () {
        if (!confirm(no + ' 을(를) 삭제하시겠습니까?')) return;
        $.ajax({
            type: 'get',
            url: '/notice/delete',
            data: {
                'no': no
            },
            success: function (data) {
                alert('삭제되었습니다.');
                location.href = '/notice';
            }
        });
    });

    // 수정 submit
    $(frm).on('submit', function (e) {
        e.preventDefault(); // submit을 박는다.
        var title = $(frm.title).val();
        if (title === '') {
            alert("제목을 입력하세요.");
            $(frm.title).focus();
            return;
        };
        var content = $(frm.content).val();
        if (content === '') {
            alert("내용을 입력하세요.");
            $(frm.content).focus();
            return;
        };

        // !가 붙었으니 false면 return이 된다.
        if (!confirm('글을 수정하시겠습니까?')) return;

        // 내용을 update 하는 작업
        $.ajax({
            type: 'post',
            url: '/notice/update',
            data: {'no':no, 'title':title, 'content':content},
            success:function(){
                alert('수정이 완료되었습니다!');
                location.href='/notice';
            }
        });
    });
</script>

 

 

- 더보기 버튼을 통해서 공지사항 추가 출력하기

- back to mysql

- 더미 데이터를 자가 복사하여 만들어준다.

insert into notice(title, content)
select title, content from notice;

 

- back to VSC

C:\data\node\ex06\views\notice.ejs

<span id="more">더보기</span>

<script>
    // 변수 선언
    var nPage = 1; // new

    getList();

    // #more click // new
    $('#more').on('click',function(){
        nPage++;
        getList();
    });

    // 공지사항 출력
    function getList() {
        $.ajax({
            type: 'get',
            url: '/notice/notice.json',
            dataType: 'json',
            data:{'page':nPage}, // new
            success: function (data) {
                var str = '';
                $(data).each(function () {
                    var no = this.no;
                    var title = this.title;
                    var date = this.fdate;
                    str += `<tr class="row" onClick="location.href='/notice/read?no=${no}'">`;
                    str += `<td class="no">[${no}]</td>`;
                    str += `<td><div class="title">${title}</div></td>`;
                    str += `<td class="date">${date}</td>`;
                    str += `</tr>`;
                });
                $('#tbl').append(str);
            }
        });
    };
</script>

 

C:\data\node\ex06\routes\notice.js

/* GET 공지사항목록*/
router.get('/notice.json', function (req, res) {
  var page = parseInt(req.query.page); // new
  var start = (page - 1) * 4; // new
  var sql = 'select *,date_format(wdate,"%Y-%m-%d %h:%i:%s") fdate from notice order by no desc limit ?,4;'; // new
  db.get().query(sql, [start], function (err, rows) { // new
    res.send(rows);
  });
});

 

 

 

- prev, next 버튼을 통해서 페이지 넘기고 남은 페이지 현재 페이지 출력하기. 첫번째 마지막 페이지에서는 disabled 하기.

C:\data\node\ex06\views\notice.ejs

<table id="tbl"></table>
<!-- <span id="more">더보기</span> -->
<div style="width: 900px; text-align: center; margin: 10px;"> <!--new-->
    <button id="prev" disabled="true">&lt;</button>
    <span id="page">1</span>
    <button id="next">&gt;</button>
</div>
<script>
    // 변수 선언
    var page = 1; // new

    getList();

    // #more click
    // $('#more').on('click',function(){
    //     nPage++;
    //     getList();
    // });

    // #prev click // new
    $('#prev').on('click', function () {
        page--;
        getList();
    });

    // #next click // new
    $('#next').on('click', function () {
        page++;
        getList();
    });

    // 공지사항 출력
    function getList() {
        $.ajax({
            type: 'get',
            url: '/notice/notice.json',
            dataType: 'json',
            data: {
                'page': page
            },
            success: function (data) {
                var str = '';
                $(data.rows).each(function () {
                    var no = this.no;
                    var title = this.title;
                    var date = this.fdate;
                    str += `<tr class="row" onClick="location.href='/notice/read?no=${no}'">`;
                    str += `<td class="no">[${no}]</td>`;
                    str += `<td><div class="title">${title}</div></td>`;
                    str += `<td class="date">${date}</td>`;
                    str += `</tr>`;
                });
                $('#tbl').html(str);
                var count = data.count; // 상품수 // new
                var lastPage = Math.ceil(count/4); // new
                $('#page').html(`${page}/${lastPage}`); // new
                // 첫번째 페이지 마지막 페이지 버튼 비활성화 // new
                if (page == 1) $('#prev').attr('disabled', true);
                else $('#prev').attr('disabled', false);

                if (page == lastPage) $('#next').attr('disabled', true);
                else $('#next').attr('disabled', false);
            }
        });
    };
</script>

 

C:\data\node\ex06\routes\notice.js

/* GET 공지사항목록*/
router.get('/notice.json', function (req, res) {
  var page = parseInt(req.query.page);
  var start = (page - 1) * 4;
  var sql = 'select *,date_format(wdate,"%Y-%m-%d %h:%i:%s") fdate from notice order by no desc limit ?,4;';
  db.get().query(sql, [start], function (err, rows) {
    // res.send(rows);
    var data = rows;
    sql = 'select count(*) cnt from notice;';
    db.get().query(sql,[],function(err,rows){
      var count = rows[0].cnt;
      res.send({'rows':data,'count':count})
    });
  });
});