본문 바로가기
코딩과 알고리즘

node.js express | 템플릿 쪽지함#6. 쪽지 데이터베이스 저장

지난 스토리에서는 MYSQL 커뮤니티 서버를 서버에 설치하였지요.

https://itadventure.tistory.com/442

 

node.js express | 템플릿 쪽지함#5. AWS 에 MYSQL 설치

이틀 가량 중 짜투리 시간을 투자해서 node.js 에서 쪽지불러오기 및 저장 부분을 완성했습니다. C나 C#과는 좀 다른 스타일의 난이도가 있더군요 ㅎ.. 약간 사용법이 까다롭다고 보면 될것 같습니

itadventure.tistory.com

이어서 node.js 에서 MYSQL 서비스를 이용하여 쪽지함을 구성하는 소스를 다뤄보도록 하겠습니다.

우선 전체 소스를 한번에 구성하고 뭔지 구경부터 해보도록 하지요.
( 실제 개발은 점진적으로 한 단계씩 진행하는 것입니다. 누구든지 한번에 짠 하고 개발을 완성할 수는 없지요 :) )

리눅스 터미널에서 새 폴더를 생성하고 개발환경을 세팅합니다.
반복된 내용이니 한번에 실행 스크립트를 나열하도록 하겠습니다.

sudo mkdir /home/nodejs6
sudo chown ec2-user:ec2-user /home/nodejs6
cd /home/nodejs6
npm init -y
npm install express 
npm install ejs
npm install body-parser
npm install mysql2
mkdir views

예전과 달라진 부분으로는 mysql2 모듈을 설치해주는 부분이 추가되었습니다.

"어? mysql 은 지난 번에 설치하지 않았나요? 또 설치하나요"

좋은 질문입니다 :) 지난번에도 MYSQL 을 설치했었지요.
사실 지난 스토리에서 설치한 MYSQL은 MYSQL 서버 또는 MYSQL 서비스라고 부릅니다.

이 MYSQL 서버는 많은 컴퓨터 언어들이 연결해서 사용할 수 있는데요.
node.js 도 그 언어들 중 하나입니다.

그 때 컴퓨터 언어마다 자기 특성에 맞는 MYSQL 서버에 연동할 수 있는 연결 도구가 필요합니다.
node.js 에서는 그것이 mysql2 모듈입니다.

우선 지난번에 이어서 root 권한 상태라면 exit 명령으로 ec2-user 로 빠져나옵니다.
터미널에 ec2-user 아이디로 새로 로그인했다면 상관 없습니다.


이제 소스를 구성해 보겠습니다.
편하신 방법에 따라 vi 가 아닌 다른 도구를 사용하셔도 되겠습니다.
먼저 main.js 를 구성하고

vi main.js

 

const express=require('express');
const bodyParser = require('body-parser');
const ejs=require("ejs");
const app=express();
const db = require('./db')
const memoClass = require("./memoclass");
  // 함축의 의미
  // const memoModule = require("./memoclass");
  // const memoClass = memoModule.memoClass;
const memo = new memoClass();

// 템플릿 엔진과 폴더 설정
app.set('view engine', 'ejs');
app.set('views', './views');

// public 폴더하위의 파일들을 기본으로 서비스
app.use(express.static('public'));

// json post 를 사용하려면 추가
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended : true}));

// 쪽지를 불러온다
memo.loading(db);

// 쪽지 목록
app.get('/memo', function(req,res) {
  res.render('memo', {
    memo: memo.list
  });
});

// 쪽지 추가
app.post('/memoadd', function(req,res) {
  // async 내에서는 순차 실행
  (async () => {
    try {
      let result = await memo.add(db, req.body.msg);
      if(result)res.json({result: 'ok'});
      else res.json({result: 'fail'});
    }
    catch (err) {
      res.json(err);
    }
  })();
});

// 페이지를 찾을 수 없음 오류 처리
app.use(function(req, res, next) {
  res.status(404);
  res.send(
    '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">' +
    '<html><head><title>404 페이지 오류</title></head>' +
    '<body><h1>찾을 수 없습니다</h1>' +
    '<p>요청하신 URL ' + req.url + ' 을 이 서버에서 찾을 수 없습니다..</p><hr>' +
    '</body></html>'
  );
});

app.listen(8080, function() {});

메모 클래스 소스인 memoclass.js 를 구성합니다.

vi memoclass.js
// 쪽지 클래스
class memoClass {
  constructor(){
    this.list=Array();
  }

  getRandom(min,max){
    return Math.floor(Math.random()*(max-min+1)+min);
  }

  async loading(db){
    try {
      const data = await db.query(
        'SELECT x, y, r, memo FROM memolist'
      );
      let result=data[0];

      for(var i=0;i<result.length;++i)
        this.list.push({
          x: result[i].x,
          y: result[i].y,
          r: result[i].r,
          memo: result[i].memo
        });
      console.log(this.list);
      console.log(
        "[ " + result.length
        + " ] 개의 쪽지가 로딩되었습니다."
      );
    } catch (err) {
      console.log(err.message);
    }
  }

  async add(db, msg){
    let x=this.getRandom(0,700);
    let y=this.getRandom(0,500);
    let r=this.getRandom(-20,20);
    // MYSQL 쿼리 실행
    try {
      const result = await db.query(
        "INSERT INTO memolist SET x = ?, y = ?, r = ?, memo = ?",
        [ x, y, r, msg ]
      );
      this.list.push({
        x: x,
        y: y,
        r: r,
        memo: msg
      });
      console.log("쪽지가 추가되었습니다.");
      return await true;
    } catch (err) {
      console.log(err.message);
      return await false;
    }
  }
}

module.exports = memoClass;


데이터베이스에 연결할 DB정보를 갖는 db.js 파일도 구성합니다.
아이디와 패스워드는 지난번에 cray, 4321 로 정했지만 다른 계정정보를 추가했다면 그 내용대로 수정해서 입력해 주세요.

vi db.js
const mysql = require('mysql2/promise')

const db = mysql.createPool({
  host: 'localhost',
  port: 3306,
  user: 'cray',
  password: '4321',
  database: 'myroom'
})

module.exports = db


그리고 템플릿 소스를 구성합니다.
템플릿 소스는 아주 약간 변경되었습니다.

vi views/memo.ejs
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>메모장</title>
  </head>
  <style>
  .memolayer {
    background-color:#eff;
    float:left;
    border-top:1px solid green;
    border-left:1px solid green;
    border-bottom:2px solid green;
    border-right:2px solid green;
    padding:3px;
    margin:5px;
    width:120px;
    height:120px;
    font-family: 'Nanum Pen Script', cursive;
    font-size:16pt;
    color:green;
  }
  </style>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Nanum+Pen+Script&display=swap" rel="stylesheet">
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <script>
  function input_memo(){
    var msg=prompt("명언을 입력해 보세요", "");
    if(msg!='' && msg!=undefined){
      $.ajax({
        url: '/memoadd',
        type: 'post',
        dataType: 'json',
        data: { msg: msg },
        success: function(data){
          console.log(data);
          if(data.result=='ok')location.reload();
          else if(data.result=='fail')alert("쪽지 추가가 실패했습니다.");
          else alert(data.result);
        },
        error: function(response){
          console.log(response);
        }
      });
    }
  }
  </script>
  <body>
    <h1>크레이의 쪽지쉼터</h1>
    <hr/>
      <% for (var i = 0; i <=memo.length-1;  i++ ) { %>
        <div class='memolayer' style="position:absolute;left:<%= memo[i].x %>px;top:<%= memo[i].y + 75 %>px;transform: rotate( <%= memo[i].r %>deg )">
           <%= memo[i].memo %><br/>
        </div>
        <% } %>
        <div class='memolayer' style="position:absolute;top:0px; left:740px; width:60px; height:60px;">
           <input type=button value="+" style="width:60px;height:60px;font-size:30pt;" onclick="input_memo()">
        </div>
  </body>
</html>


이 것으로 소스는 구성되었지만,
쪽지를 저장하려면 쪽지를 저장할 틀을 마련해주어야 합니다.

MYSQL 에 로그인해서 테이블을 생성하는 방법도 있지만,
여기서는 node.js 소스로 테이블을 생성해보도록 합시다.

아래 소스를 구성합니다.

vi dbcreate.js
const mysql = require('mysql2/promise');
const db = require('./db')

const Main = async()=>{

	// 테이블 생성  
	await db.query(
	`create table if not exists memolist (
	  number int primary key auto_increment,
	  x int,
	  y int,
	  r int,
	  memo text not null
	)`);
	console.log("테이블이 생성되었습니다.\n");
	process.exit();
};

Main();

이제 이 소스를 실행하여 MYSQL 내에 테이블을 생성합니다.

node dbcreate.js


테이블이 생성되었는지 확인하시려면 MYSQL 콘솔에 접속해 보시면 됩니다.

mysql -ucray -p myroom


그리고 show tables;  명령을 내려주면 생성된 테이블을 보실수 있습니다.

show tables;

간혹 뒤에 세미콜론 기호를 뺴먹을 수 있는데요.

show tables

그 때는 세미콜론 기호만 추가로 입력해주시면 됩니다.


테이블에 대한 설명은 나중에 또 진행하기로 하고 exit 명령으로 MYSQL 콘솔을 빠져나오신 다음에

exit

이제 node.js 를 실행합니다.

node main.js


그리고 여느 때처럼 웹브라우저를 실행, 쪽지 페이지를 엽니다.

퍼블릭IP:8080/memo

쪽지가 하나도 없습니다. 이번 소스에서는 기본 쪽지를 넣어두지 않았기 때문인데요.
이제 쪽지를 하나씩 추가해 보세요.

크레이는 성서의 잠언 2장을 한 구절씩 쪽지로 나열해 보았습니다.

자, 이제 이 쪽지는 MYSQL 서버 내에 myroom 데이터베이스 내에 memolist 라는 테이블이라는 곳에 보관되어 있기 때문에 유실되지 않습니다.

정말인가 볼까요?
터미널창에서 실행중이던 node 서버를 중지하고 ( Ctrl + C 키 )

다시 node를 실행해 보세요.

node main.js

그러면 실행되면서 저장되었던 쪽지가 데이터베이스로부터 주루룩 읽혀질것입니다.
MYSQL 데이터베이스에 영구 보관되었기 때문이지요.

웹 브라우저를 통해 다시 띄워봐도,
지난번과는 다르게 쪽지가 모두 살아 있는 것을 보실 수 있습니다.

퍼블릭IP:8080/memo


여기까지 잘 실행에 성공하셨나 모르겠습니다.

node.js 의 특별한 부분들 때문에 소스만 보고 모든 것을 이해하기에는 좀 모호한 부분이 있을텐데요.
다음 스토리부터 설명 부분을 진행하도록 하겠습니다.

오늘도 여기까지 읽어주셔서 감사합니다.
구독과 좋아요는 ♥ 이죠 :)


다음 스토리 : mysql2 프로미스

https://itadventure.tistory.com/444

 

node.js express | #7. mysql2 프로미스

지난 스토리에서 다루었던 쪽지 템플릿에는 MYSQL 이라는 저장하는 부분을 비롯하여 클래스라는 부분까지 여러 요소가 추가되었는데요. node.js의 프로미스라는 특징적 부분까지 다루어야 해서 예

itadventure.tistory.com