본문 바로가기
ICIA 수업일지

2021.08.04 수업일지(node.js, MySQL, VSC)

by 주성씨 2021. 8. 7.

https://becomefullstackdev.tistory.com/47

 

 

1. node. js 설치 https://nodejs.org/ko/ Node.js Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. nodejs.org 해당 홈페이지에 들어가서 자신의 운영체제에 맞는 버젼을 다운받아서..

becomefullstackdev.tistory.com

 

- powershell 권한 변경하기

위와 같은 경로로 powershell에 들어갈 수 있다.

 

ExecutionPolicy (현재정책확인) -> Restricted 인지 확인
set-ExecutionPolicy Unrestricted (정책을 제안 해제) -> Unrestricted 로 설정

 

- express에서 데이터를 입력받아서 웹상에 출력하는 과정

애플리케이션 레벨과 라우터 레벨은 실행단계의 차이지 기능적으로는 다른 점이 없다. 애플리케이션 분기 + 라우터 분기로 더 세세허게 요청 URL(파일 경로로 생각하자)을 분리하여 제어가 가능하다는 점이다.

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

 

애플리케이션 단계에서 '/'와 '/users'로 URL을 분리하여 처리를 하도록 한것이다. 

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

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: '식도락 여행' });
});

module.exports = router;

위의 코드는 라우터 단계의 미들웨어이다. app.use()처럼 router.use()도 쓸 수 있고 app,method()처럼 router.method()도 사용 가능하다. 다른점은 use()는 모든 METHOD에서 동작한다는 것이고 METHOD()는 지정된 요청 (GET, POST, PUT, DELETE 등)에서만 동작을 한다는 것이다.

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1><%= title %></h1>
    <p>Welcome to <%= title %></p>
  </body>
</html>

router를 통해서 받은 index.js의 title값을 <%= title %>의 형태로 받아서 웹상에 출력할 수 있다. 필자는 '식도락 여행' 페이지 명을 설정했으니 아래와 같이 나올 수 있다.

 

 

- 익스프레스의 index.ejs를 수정하여 웹페이지를 꾸며보자.

EJS는 Embedded JavaScript templating의 약어로서, 자바스크립트로 HTML 마크업을 생성할 수 있는 간단한 템플릿 언어이다. (JSP와 동일한 역할을 한다.)

- 초기본

ex02>app.js

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

 

[new] ex02>routes>photos.js

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

/* GET users listing. */
router.get('/', function(req, res, next) {
  res.send([
      {id: 1, image:'/images/img01.jpg', title:'명태냉면1인분', price: 8700},
      {id: 2, image:'/images/img02.jpg', title:'오징어볶음1인분', price: 8900},
      {id: 3, image:'/images/img03.jpg', title:'채끝 찹스테이크', price: 9100},
      {id: 4, image:'/images/img04.jpg', title:'플랫브레드루꼴라피자1인분', price: 8900},
      {id: 5, image:'/images/img05.jpg', title:'불락전골1인분', price: 10900},
      {id: 6, image:'/images/img06.jpg', title:'닭볶음탕1인분', price: 7800},
      {id: 7, image:'/images/img07.jpg', title:'자장밥1인분', price: 2800},
      {id: 8, image:'/images/img08.jpg', title:'황태양념구이1인분', price: 7800},
  ]);
});

module.exports = router;

 

[new] ex02>routes>notice.js

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

/* GET users listing. */
router.get('/', function(req, res, next) {
  res.send([
      {id: 1, title:'자기의 일은'},
      {id: 2, title:'스스로 하자'},
      {id: 3, title:'알아서 척척'},
      {id: 4, title:'스스로 어른'},
      {id: 5, title:'와아아 아아'},
  ]);
});

module.exports = router;

 

ex02>routes>views>index.ejs

<!DOCTYPE html>
<html>

<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>

<body>
  <div id="container">
    <div id="header">
      <img src="http://placehold.it/140/140" width="140" height="140" id="image"/> <!--인터벌로 이미지 넣을곳-->
      <img src="/images/download.jpg" width="750" />
    </div>
    <div id="content">
      <h3>[라이언 MD의 추천상품]</h3>
      <div id="photos"></div>
      <h3>[SNS 고객후기]</h3>
      <div id="slider">
        <!-- 실제 보여지는 부분-->
        <div id="foods"></div> <!-- 이미지 집합-->
      </div>
      <div id="pagination">
        <button id="prev" disabled>&lt;</button> <!-- &lt; <-->
        <button id="next">&gt;</button> <!-- &gt; >-->
      </div>
      <h3>[공지사항]</h3>
      <table id="tbl">
      </table>
    </div>
    <div id="footer">
      <h3>Copyright ICIA 이주성</h3>
    </div>
  </div>
</body>
<script>
  let page = 0;
  //다음 버튼 클릭
  $('#next').on('click', function () {
    page++;
    change();
  });

  //이전 버튼 클릭
  $('#prev').on('click', function () {
    page--;
    change();
  });

  //이미지이동
  function change() {
    $('#foods').animate({
      left: -page * 110
    }, 1000);
    if (page == 0) $('#prev').attr('disabled', true);
    else $('#prev').attr('disabled', false);
    if (page == 3) $('#next').attr('disabled', true);
    else $('#next').attr('disabled', false);
  };

  let images =[];

  // 슬라이드로 이미지 출력
  $.ajax({
    type: 'get',
    url: '/photos',
    dataType: 'json',
    success: function (data) {
      let str = '';
      $(data).each(function () {
        let image = this.image;
        images.push(image);
        let id = this.id;
        str += '<div class="item">';
        str += `<img src="${image}" width="100"/>`;
        str += `<div>${id}</div>`;
        str += '</div>';
      });
      $('#foods').html(str);
    }
  });

  let index=0;
  $('#image').attr('src', images[index]);

  setInterval(() => {
    $('#image').attr('src',images[index % 5]);
    index++;
  }, 1500);

  // 8(4*2)개의 상품이미지 출력
  $.ajax({
    type: 'get',
    url: '/photos',
    datatype: 'json',
    success: function (data) {
      let str = '';
      $(data).each(function () {
        let id = this.id;
        let image = this.image;
        let title = this.title;
        let price = this.price
        if (id <= 8) {
          str += '<div class="box">';
          str += `<img src="${image}"/>`;
          str += `<div class="title">${id} : ${title}</div>`
          str += `<div class="price">${price}원</div>`
          str += '</div>';
        };
        $('#photos').html(str);
      })
    }
  })

    // 공지사항 출력하기
    $.ajax({
    type: 'get',
    url: '/notice',
    dataType: 'json',
    success:function(data){
      let str ='';
      $(data).each(function(){
        let id = this.id;
        let title = this.title;
        str += '<tr>'
          str += `<td>${id} : ${title}</td>`
        str += '</tr>'
      });
      $('#tbl').html(str);
    }
  })
</script>

</html>

 

[new] ex02>public>stylesheets>style.css

#container {
  width: 940px;
  margin: 10px auto;
  padding: 20px;
  border: 1px solid orange;
  }
 #header {
  padding: 20px; 
  margin-bottom: 20px;
  border: 1px solid orange;
 }
 #content {
  width: 900px;
  padding: 20px;
  margin-bottom: 20px;
  float: left;
  border: 1px solid orange;
 }
 #content {
   text-align: center;
 }
 #sidebar {
  width: 260px;
  padding: 20px;
  margin-bottom: 20px;
  float: right;
  border: 1px solid orange;
 }
 #footer {
  clear: both;
  padding: 20px;
  border: 1px solid orange;
 }
 #footer h3 {
   text-align: center;
 }
 #photos{
   overflow: hidden;
 }
 .box{
   width: 210px;
   float: left;
   border: 1px solid yellow;
   margin: 5px;
   box-shadow: 10px 10px 10px yellowgreen;
 }
 .box .title{
   white-space: nowrap;
   overflow: hidden;
   text-overflow: ellipsis;
   margin: 5px;
 }
 #slider{
   margin: 0px auto;
   position: relative;
   overflow: hidden;
   width: 550px;
   height: 150px;
 }
 #foods{
   position: absolute;
   overflow: hidden;
   width: 880px;
   /* 8개가 들어가야해서 880px */
  }
  .item{
    width: 100px;
    margin-left: 10px;
   float: left;
 }
 #pagination{
   width: 500px;
   margin: 0px auto;
   text-align: center;
 }
 #tbl{
   width: 800px;
   margin: 0px auto;
 }
 td{
   border-bottom: 1px solid orange;
   padding-bottom: 10px;
 }

초기본 출력물

 

- MySQL - DB에 정보를 입력하고 그 정보를 넣어보자

※ db를 사용하기전에 'use (해당db명);' 을 입력하도록 하자

 

 

이런식으로 스키마에서 사용할 DB가 굵게 표시가 되야한다.

 

 

# product table 생성
create table product(
	id int auto_increment primary key,
    title nvarchar(100),
    price int,
    image nvarchar(100)
    );

# product tabble column 확인
desc product;

# product table data insert
insert into product(title,price,image) values('명태냉면1인분',8700,'/images/img01.jpg');
insert into product(title,price,image) values('오징어볶음1인분',8900,'/images/img02.jpg');
insert into product(title,price,image) values('채끝 찹스테이크',9100,'/images/img03.jpg');
insert into product(title,price,image) values('플랫브레드루꼴라피자1인분',8900,'/images/img04.jpg');
insert into product(title,price,image) values('불락전골1인분',10900,'/images/img05.jpg');
insert into product(title,price,image) values('닭볶음탕1인분',7800,'/images/img06.jpg');
insert into product(title,price,image) values('자장밥1인분',2800,'/images/img07.jpg');
insert into product(title,price,image) values('황태양념구이1인분',7800,'/images/img08.jpg');

# product table data 확인
SELECT 
    *
FROM
    product;

 

- 입력한 DB data를 VSC에서 넣도록 하자.

ctrl + c 입력하여 터미널에서 나온다.

 

npm install mysql 을 터미널에 입력한다.

 

위와 같이 확인가능하다.

 

/db.js

데이터베이스를 연동하는 방법은 두 가지가 있다. 첫 번째는 매번 데이터베이스의 커넥션을 얻어서 사용하는 방법이고, 두 번째는 커넥션 풀을 생성해 서 커넥션을 미리 생성한 후에 하나씩 꺼내서 사용하는 방법이다. 커넥션 생성 비용은 매우 크므로 가능하면 커넥션 풀을 사용하는 것이 좋다. 이 파 일에는 두 개의 함수가 있다. connect는 데이터베이스 커넥션 풀을 생성하는 함수이고, get은 생성한 커넥션 풀을 반환하는 함수이다. get 함수를 통해 풀을 반환받은 후에 데이터베이스에 질의를 실행할 수 있다.

[new] ex02>db.js

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

위와 같이 ex02에 db.js를 만들고 다음과 같이 이용할 db의 유저명과 비밀번호 db명을 수정한다.

 

app.js 하단에 이와 같이 입력한다.

// DB 연결 / ; 꼭대기 ./ ; 같은폴더 ../ ; 한단계 위
var db =require('./db',);
db.connect(function(){
  if(err){
    console.log('<DB ERROR>');
    process.exit(1); // error 발생 시 exit
  }else{
    console.log('<Connected to the MySQL server>');
  }
});

module.exports = app;

 

photos.js을 다음과 같이 수정한다. Mysql에서 data를 받아온다.

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

/* GET users listing. */
router.get('/', function(req, res) {
/* format like $,$$$ */
  var sql ='select *, format(price,0) fmt from product order by price desc';
  db.get().query(sql, [], function(err, rows){
    if(err) return res.sendStatus(400);
    res.status(200).json(rows);
  });
});

module.exports = router;

 

제대로 됐으면 브라우저에서 아래와 같이 확인이 가능하다.
http://localhost:3000/photos/

연결이 되었으면 위와 같이 확인이 가능하다.

 

 

- select tag option을 이용해서 정렬을 할 수 있는 tag를 만들어보자.

index.ejs

      <h3>[라이언 MD의 추천상품]</h3>
      <div style="width: 900px; padding-left: 50px; text-align: left;">
        <select id="key">
          <option value="id">상품등록순</option>
          <option value="price desc">상품고가순</option>
          <option value="price">상품저가순</option>
          <option value="title">상품명순</option>
        </select>
      </div>
      <div id="photos"></div>
      <h3>[SNS 고객후기]</h3>

h3와 div id='photos' 사이에 div>select>option을 추가한다.

  getLIst(); // *****
  //정렬값을 변경할 경우
  $('#key').on('change',function(){
    getLIst();
  });

script 맨 앞에 위 코드를 추가한다.

  // 8(4*2)개의 상품이미지 출력 + option에서 key 값을 받아 data에 넣는다.
  function getLIst(){
  $.ajax({
    type: 'get',
    url: '/photos',
    datatype: 'json',
    data : {'key':$('#key').val()}, //*****
    success: function (data) {
      let str = '';
      $(data).each(function () {
        let id = this.id;
        let image = this.image;
        let title = this.title;
        let price = this.fmt;
        if (id <= 8) {
          str += '<div class="box">';
          str += `<img src="${image}" style="width:150px; height:150px"/>`; //*****
          str += `<div class="title">${id} : ${title}</div>`
          str += `<div class="price">${price}원</div>`
          str += '</div>';
        };
        $('#photos').html(str);
      })
    }
  })};

8개의 이미지를 출력해서 option 클릭으로 key값에 따라서 정렬하는 function getList()로 묶는다.

 

 // 슬라이드로 이미지 출력
  $.ajax({
    type: 'get',
    url: '/photos',
    dataType: 'json',
    data: {'key': 'id'}, //*****
    success: function (data) {
      let str = '';
      $(data).each(function () {
        let image = this.image;
        images.push(image);
        let id = this.id;
        str += '<div class="item">';
        str += `<img src="${image}" width="100"/>`;
        str += `<div>${id}</div>`;
        str += '</div>';
      });
      $('#foods').html(str);
    }
  });

슬라이드 이미지도 나올 수 있도록 data를 설정하도록 한다.

 

저가 정렬로 위와 같은 출력물을 받을 수 있다.

 

- 최종본

ex02>routes>notice.js

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

/* GET users listing. */
router.get('/', function(req, res, next) {
  res.send([
      {id: 1, title:'자기의 일은'},
      {id: 2, title:'스스로 하자'},
      {id: 3, title:'알아서 척척'},
      {id: 4, title:'스스로 어른'},
      {id: 5, title:'와아아 아아'},
  ]);
});

module.exports = router;

 

ex02>routes>photos.js

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

/* GET users listing. */
router.get('/', function(req, res) {
  var key = req.query.key;
  var sql =`select *, format(price,0) fmt from product order by ${key}`;
  db.get().query(sql, [], function(err, rows){
    if(err) return res.sendStatus(400);
    res.status(200).json(rows);
  });
});

module.exports = router;

 

ex02>views>index.ejs

<!DOCTYPE html>
<html>

<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>

<body>
  <div id="container">
    <div id="header">
      <img src="http://placehold.it/140/140" width="140" height="140" id="image"/> <!--인터벌로 이미지 넣을곳-->
      <img src="/images/download.jpg" width="750" />
    </div>
    <div id="content">
      <h3>[라이언 MD의 추천상품]</h3>
      <div style="width: 900px; padding-left: 50px; text-align: left;">
        <select id="key">
          <option value="id">상품등록순</option>
          <option value="price desc">상품고가순</option>
          <option value="price">상품저가순</option>
          <option value="title">상품명순</option>
        </select>
      </div>
      <div id="photos"></div>
      <h3>[SNS 고객후기]</h3>
      <div id="slider">
        <!-- 실제 보여지는 부분-->
        <div id="foods"></div> <!-- 이미지 집합-->
      </div>
      <div id="pagination">
        <button id="prev" disabled>&lt;</button> <!-- &lt; <-->
        <button id="next">&gt;</button> <!-- &gt; >-->
      </div>
      <h3>[공지사항]</h3>
      <table id="tbl">
      </table>
    </div>
    <div id="footer">
      <h3>Copyright ICIA 이주성</h3>
    </div>
  </div>
</body>
<script>
  getLIst();
  //정렬값을 변경할 경우
  $('#key').on('change',function(){
    getLIst();
  });

  let page = 0;
  //다음 버튼 클릭
  $('#next').on('click', function () {
    page++;
    change();
  });

  //이전 버튼 클릭
  $('#prev').on('click', function () {
    page--;
    change();
  });

  //슬라이드 버튼 이미지 이동
  function change() {
    $('#foods').animate({
      left: -page * 110
    }, 1000);
    if (page == 0) $('#prev').attr('disabled', true);
    else $('#prev').attr('disabled', false);
    if (page == 3) $('#next').attr('disabled', true);
    else $('#next').attr('disabled', false);
  };

  let images =[];

  // 슬라이드로 이미지 출력
  $.ajax({
    type: 'get',
    url: '/photos',
    dataType: 'json',
    data: {'key': 'id'}, //*****
    success: function (data) {
      let str = '';
      $(data).each(function () {
        let image = this.image;
        images.push(image);
        let id = this.id;
        str += '<div class="item">';
        str += `<img src="${image}" width="100"/>`;
        str += `<div>${id}</div>`;
        str += '</div>';
      });
      $('#foods').html(str);
    }
  });

  let index=0;
  $('#image').attr('src', images[index]);

  setInterval(() => {
    $('#image').attr('src',images[index % 5]);
    index++;
  }, 1500);

  // 8(4*2)개의 상품이미지 출력 + option에서 key 값을 받아 data에 넣는다.
  function getLIst(){
  $.ajax({
    type: 'get',
    url: '/photos',
    datatype: 'json',
    data : {'key':$('#key').val()}, //*****
    success: function (data) {
      let str = '';
      $(data).each(function () {
        let id = this.id;
        let image = this.image;
        let title = this.title;
        let price = this.fmt;
        if (id <= 8) {
          str += '<div class="box">';
          str += `<img src="${image}" style="width:150px; height:150px"/>`; //*****
          str += `<div class="title">${id} : ${title}</div>`
          str += `<div class="price">${price}원</div>`
          str += '</div>';
        };
        $('#photos').html(str);
      })
    }
  })};

    // 공지사항 출력하기
    $.ajax({
    type: 'get',
    url: '/notice',
    dataType: 'json',
    success:function(data){
      let str ='';
      $(data).each(function(){
        let id = this.id;
        let title = this.title;
        str += '<tr>'
          str += `<td>${id} : ${title}</td>`
        str += '</tr>'
      });
      $('#tbl').html(str);
    }
  })
</script>

</html>

 

ex02>app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

// [new]
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/photos', require('./routes/photos'));
app.use('/notice', require('./routes/notice'));


// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

// [new]
// DB 연결 / ; 꼭대기 ./ ; 같은폴더 ../ ; 한단계 위
var db =require('./db',);
db.connect(function(){
  if(err){
    console.log('<DB ERROR>');
    process.exit(1);
  }else{
    console.log('<Connected to the MySQL server>');
  }
});

module.exports = app;

 

ex02>db.js

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

 

위와 같이 사용할 수 있다.