[20/12/04] - TIL โŽฎ ChatterBox Database

NOWANDHEREยท2020๋…„ 12์›” 4์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
53/53
post-thumbnail

12์›” 04์ผ (๊ธˆ)

๐ŸŒป Today I Learned Database with MySQL

๐Ÿ‘จ๐Ÿผโ€๐Ÿ’ป ChatterBox Database


์ด๋ฒˆ ์Šคํ”„๋ฆฐํŠธ๋Š” Chatterbox Server๊ฐ€ ์˜์†์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค. MySQL์„ ํ†ตํ•ด ๋‚˜์˜ ๋กœ์ปฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ์ดํ„ฐ๋“ค์„ ์ €์žฅํ•˜๊ณ , ์„œ๋ฒ„๊ฐ€ ์žฌ์‹œ์ž‘ํ•ด๋„ ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ง€์›Œ์ง€์ง€ ์•Š๊ฒŒ ํ•ด์•ผํ•œ๋‹ค.


1. ์Šคํ‚ค๋งˆ ์ž‘์„ฑ


๋จผ์ € Chatterbox Server์— ํ•„์š”ํ•œ ์Šคํ‚ค๋งˆ๋ฅผ ๋””์ž์ธํ–ˆ๋‹ค. server/schema.sql ํŒŒ์ผ์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์˜ ๊ตฌ์กฐ๋ฅผ ์ •์˜ํ•˜๊ณ  MySQL ์„œ๋ฒ„์— ๋กœ๋“œํ•  CREATE TABLE ๋ฌธ์„ ์ž‘์„ฑํ–ˆ๋‹ค. messages ํ…Œ์ด๋ธ” ๊ตฌ์กฐ์—๋Š” username, text, date, roomname์ด ํฌํ•จ๋˜๊ณ , users ํ…Œ์ด๋ธ” ๊ตฌ์กฐ์—๋Š” username์ด ํฌํ•จ๋˜๊ฒŒ ์ž‘์„ฑํ–ˆ๋‹ค.

schema.sql

DROP DATABASE IF EXISTS chat; // ๋งŒ์•ฝ ์ด๋ฏธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์กด์žฌํ•˜๋ฉด
CREATE DATABASE chat;         // ์—†์• ๊ณ  ์ƒˆ๋กœ ๋งŒ๋“ ๋‹ค
USE chat;

// messages ํ…Œ์ด๋ธ”
CREATE TABLE messages (
  id int not NULL PRIMARY KEY AUTO_INCREMENT,
  username varchar(255) not NULL,
  text text(1024),
  date timestamp not NULL DEFAULT CURRENT_TIMESTAMP,
  roomname varchar(255) not NULL
);

// users ํ…Œ์ด๋ธ”
CREATE TABLE users (
  id int not NULL PRIMARY KEY AUTO_INCREMENT,
  username varchar(255) not NULL
);

์•„๋ž˜ ์‚ฌ์ง„์€ mysql -u root -p < server/schema.sql์„ ํ†ตํ•ด ๋‚ด MySQL server์— ์ž‘์„ฑํ•œ schema.sql์„ ๋กœ๋“œํ•˜๊ณ  mysql์—์„œ ํ•ด๋‹น ๋‚ด์šฉ์„ ํ™•์ธํ•œ ๋ชจ์Šต์ด๋‹ค.

2. ์„œ๋ฒ„


์ž, ์ด์ œ ์„œ๋ฒ„๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค. ๋จผ์ € MySQL ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ณด์•ˆ์ƒ/ํŽธ์˜์ƒ ์ด์œ ๋กœ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ๋ถ„๋ฆฌํ•ด๋†“์•˜๋‹ค. ์•„๋ž˜ ํ„ฐ๋ฏธ๋„ ๋ช…๋ น์„ ํ†ตํ•ด ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜๊ณ  node.js ์ƒ์—์„œ process.env.DATABASE_SPRINT_PASSWORD๋ผ๋Š” ๋ณ€์ˆ˜์—์„œ ์„ค์ •ํ•œ ๊ฐ’์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค.

  • $ export DATABASE_SPRINT_PASSWORD='my_value'

๊ทธ๋Ÿฐ๋ฐ ์ด๋ ‡๊ฒŒ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ํ„ฐ๋ฏธ๋„์—์„œ๋Š” ์ ‘๊ทผ์ด ์•ˆ๋˜๋Š” ์ ์ด ๋ถˆํŽธํ–ˆ๊ณ , dotenv๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด .env ํŒŒ์ผ์„ ํ†ตํ•ด ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ฐฐ์› ๋‹ค.

๋‹ค์Œ์œผ๋กœ๋Š” ์ฃผ์–ด์ง„ server/app.js์—์„œ express ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ํ†ตํ•œ node.js ์„œ๋ฒ„๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ณ , server/db/index.js์—์„œ mysql npm module์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํ–‰ ์ค‘์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•œ๋‹ค.

app.js

var express = require('express');

// Middleware
var morgan = require('morgan');
var parser = require('body-parser');

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

var app = express();
module.exports.app = app;

// Set what we are listening on.
app.set('port', 3000);

// Logging and parsing
app.use(morgan('dev'));
app.use(parser.json());

// Set up our routes
app.use('/classes', router);

// Serve the client files
app.use(express.static(__dirname + '/../client'));

// If we are being run directly, run the server.
if (!module.parent) {
  app.listen(app.get('port'));
  console.log('Listening on', app.get('port'));
}

db/index.js

const mysql = require('mysql');
const password = process.env.DATABASE_SPRINT_PASSWORD;
const host = 'localhost';

// user๋Š” root, ํŒจ์Šค์›Œ๋“œ๋Š” ์œ„ password ๋ณ€์ˆ˜
// ์‹ค์ œ๋กœ ์—ฐ๊ฒฐํ•  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์œ„์น˜(host)๋Š” host ๋ณ€์ˆ˜
// ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ด๋ฆ„(database)์€ "chat"
// ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ๋งŒ๋“ค๊ณ , ์—ฐ๊ฒฐ ๊ฐ์ฒด export
module.exports = mysql.createConnection({
  host,
  user: 'root',
  password,
  database: 'chat',
});

server/models/index.js์—์„œ๋Š” ๋ฉ”์‹œ์ง€์™€ ์‚ฌ์šฉ์ž ๋ชจ๋ธ์„ ์ •์˜ํ•œ๋‹ค. SQL query๋ฌธ์„ ์ž‘์„ฑํ•˜์—ฌ ์‹ค์งˆ์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฐ€์ ธ์™€ controller์—๊ฒŒ ๋„˜๊ฒจ์ฃผ๋Š” ์—ญํ• ์„ ๋‹ด๋‹นํ•œ๋‹ค.

๋น„๋™๊ธฐ ํ˜ธ์ถœ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ํ”„๋กœ๋ฏธ์Šค ๊ฐ์ฒด๋ฅผ ๋„˜๊ฒจ์ฃผ์—ˆ๊ณ  ์ฝ”๋“œ๋Š” w3schools.com์— Node.js MySQL์„ ์ฐธ๊ณ ํ•˜์—ฌ ์ž‘์„ฑํ–ˆ๋‹ค.

models/index.js

// ์œ„์—์„œ ์ž‘์„ฑํ•œ db/index.js์—์„œ ์—ฐ๊ฒฐ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ 
var db = require('../db');

// ์—ฐ๊ฒฐํ•œ๋‹ค
db.connect((err) => {
  if (err) throw err;
  console.log('Connected!');
});

module.exports = {
  messages: {
    // a function which produces all the messages
    get: function () {
      return new Promise((resolve, reject) => {
        db.query('SELECT * FROM messages', function (err, result) {
          if (err) reject(err.message);
          resolve(result);
        });
      });
    },
    // a function which can be used to insert a message into the database
    post: function (data) {
      return new Promise((resolve, reject) => {
        const sql = 'INSERT INTO messages (username, text, roomname) VALUES ?';
        const values = [data.username, data.text, data.roomname];
        db.query(sql, [[values]], function (err) {
          if (err) reject(err.message);
          db.query('SELECT * FROM messages', function (err, result) {
            if (err) reject(err.message);
            resolve(result);
          });
        });
      });
    },
  },
  // users: {...} ์ƒ๋žต
};

server/controllers/index.js๋Š” ์„œ๋ฒ„ ๋‚ด์—์„œ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์— ์•Œ๋งž๊ฒŒ ๋ชจ๋ธ ๊ฐ์ฒด ์•ˆ์˜ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

controllers/index.js

// ์œ„์—์„œ ์ž‘์„ฑํ•œ models/index.js์—์„œ ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค
var models = require('../models');

module.exports = {
  messages: {
    // a function which handles a get request for all messages
    get: function (req, res) {
      models.messages.get().then((result) => res.send(result));
    },
    // a function which handles posting a message to the database
    post: function (req, res) {
      models.messages
        .post(req.body)
        .then((result) => res.status(201).send(result));
    },
  },
  // users: {...} ์ƒ๋žต
};

์ฃผ์–ด์ง„ server/routes.js๋Š” ์š”์ฒญ URL์— ๋”ฐ๋ผ ์„œ๋ฒ„ ๋ผ์šฐํŒ… ์—ญํ• ์„ ํ•œ๋‹ค. node.js ์›น ์„œ๋ฒ„ ์ฝ”๋“œ app.js์—์„œ ์ด ํŒŒ์ผ์„ requireํ•˜์—ฌ ๋ผ์šฐํ„ฐ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

routes.js

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

//Connect controller methods to their corresponding routes
router.get('/messages', controller.messages.get);
router.post('/messages', controller.messages.post);
router.get('/users', controller.users.get);
router.post('/users', controller.users.post);

module.exports = router;

ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ๋ช‡ ๊ฒฐ๊ณผ ๐Ÿ‘


ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ์€ ๊ธฐ์กด์— ์ง„ํ–‰ํ–ˆ๋˜ Chatterbox client sprint์˜ reference ์ฝ”๋“œ๋ฅผ ๊ฐ€์ ธ์™”๊ณ , ํ˜„์žฌ ์Šคํ”„๋ฆฐํŠธ์— client ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด ๊ทธ ์•ˆ์— ๋‹ด์•˜๋‹ค. app.js์—์„œ server URI๋ฅผ ๋‚˜์˜ ๋กœ์ปฌ MySQL ์„œ๋ฒ„๋กœ ๋ฐ”๊ฟ”์ฃผ๊ณ , fetch ํ•˜๋Š” ๋ถ€๋ถ„๊ณผ render ํ•˜๋Š” ๋ถ€๋ถ„๋งŒ ์‚ด์ง ์ˆ˜์ •ํ–ˆ๋‹ค. ๊ฒฐ๊ณผ ํ™”๋ฉด์ด๋‹ค.

์„œ๋ฒ„๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ณ , ํด๋ผ์ด์–ธํŠธ ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจํ•˜์—ฌ ๋ฉ”์‹œ์ง€ ํ•˜๋‚˜๋ฅผ post ์š”์ฒญํ•˜๋ฉด MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋˜์–ด ๋‚˜ํƒ€๋‚˜๋Š” ๋ชจ์Šต์ด๋‹ค.

๋˜ํ•œ, ์„œ๋ฒ„๋ฅผ ์žฌ์‹œ์ž‘ํ•˜์—ฌ๋„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋‚จ์•„์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์˜์†์„ฑ ์žˆ๊ฒŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๋ชจ์Šต์ด๋‹ค.


๋Š๋‚€ ์  ๐ŸŒป


์ด์ œ๋Š” ํด๋ผ์ด์–ธํŠธ์˜ HTTP ์š”์ฒญ์œผ๋กœ ์ธํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„ ์ปดํ“จํ„ฐ์˜ in-memory๋‚˜ node.js์˜ fs ๋ชจ๋“ˆ์„ ํ†ตํ•œ ํŒŒ์ผ์ด ์•„๋‹ˆ๋ผ ์„œ๋ฒ„์™€ ์—ฐ๊ฒฐ๋œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•ด ์ดํ•ดํ–ˆ๊ณ , ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€์™€ ๊ทธ ํ•„์š”์„ฑ์„ ์ธ์ง€ํ•˜๊ธด ํ–ˆ์ง€๋งŒ ์•„์ง ์Šคํ”„๋ฆฐํŠธ ์ฝ”๋“œ์˜ model, view, controller์— ๋Œ€ํ•ด์„œ๋Š” ์ž˜ ๋ชจ๋ฅด๊ฒ ๋‹ค. ์–ด์งธ์„œ ์ด๋ ‡๊ฒŒ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ด๊ณ , ์™œ ํ•„์š”ํ•œ ๊ฒƒ์ด๊ณ , ์ด๊ฒƒ์„ ์™œ MVC ๋””์ž์ธ ํŒจํ„ด์ด๋ผ ๋ถ€๋ฅด๋Š” ๊ฒƒ์ธ๊ฐ€. ๋‹ค์Œ ์Šคํ”„๋ฆฐํŠธ์—์„œ ๊ณต๋ถ€ํ•˜๊ฒŒ ๋  ๋‚ด์šฉ์ด๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋Ÿฌํ•œ ํ˜•ํƒœ์˜ ์ฝ”๋“œ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ”„๋ฆฐํŠธ๋ฅผ ํ†ตํ•ด ๋จผ์ € ์ ‘ํ•˜๊ฒŒ ํ•œ ๊ฒƒ ๊ฐ™๋‹ค.

๋ฐฐ์šฐ๋Š” ๋‹จ๊ณ„๋ผ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ‹€๋ฆฐ ๋‚ด์šฉ์€ ๋Œ“๊ธ€ ๋‹ฌ์•„์ฃผ์‹œ๋ฉด ์ˆ˜์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค :)

profile
๐ŸŒป

0๊ฐœ์˜ ๋Œ“๊ธ€