Vue + Express 웹 사이트 만들기 (3) Express와 MySQL 연동

cleopatra·2021년 1월 13일
0
post-custom-banner

드디어! 백엔드 작업을 한다!

오늘의 할 일📋

☑️ mysql에 neti 데이터베이스 생성하기
☑️ 회의실 테이블 생성하고 데이터 삽입하기
☑️ express로 회의실 테이블 CRUD API 만들기

mysql에 neti 데이터베이스 생성하기

mysql 설치는 brew 로 하거나
공식 홈페이지에서 Community server 를 받아 설치하면 된다.

mysql에 들어가서

mysql -uroot -p

neti 라는 데이터베이스를 만들자.

create database neti;

회의실 테이블 생성하고 데이터 넣기

만든 neti로 들어가서

use neti;

예전 기억을 되살려 회의실 테이블을 만들었다.
이름, 설명, 온라인 URL, 사용 여부 정도가 사용 될거고 나머지는 그냥 나만의 기본 셋이다. 😎

CREATE TABLE IF NOT EXISTS `TBL_MEETING_ROOM`
(
  ID         BIGINT      NOT NULL AUTO_INCREMENT,
  NAME  VARCHAR(50) NOT NULL,
  DESCRIPTION  VARCHAR(50) NOT NULL,
  ONLINE_URL VARCHAR(125),
  USE_YN     Boolean,
  CREATED    DATETIME(6) NOT NULL,
  CREATOR    VARCHAR(20),
  UPDATED    DATETIME(6) NOT NULL,
  UPDATER    VARCHAR(20),
  PRIMARY KEY (ID)
)
DEFAULT CHARACTER SET utf8
COLLATE utf8_general_ci
ENGINE = INNODB;

회의실은 자주 수정되는 항목이 아니라서 테스트겸 데이터도 미리 넣어주자.
4개만 넣어주자.

INSERT INTO TBL_MEETING_ROOM (NAME, DESCRIPTION, ONLINE_URL, USE_YN, CREATED, CREATOR, UPDATED, UPDATER) VALUES ('1번', '1번 회의실', null, true, now(), 'admin', now(), 'admin');

INSERT INTO TBL_MEETING_ROOM (NAME, DESCRIPTION, ONLINE_URL, USE_YN, CREATED, CREATOR, UPDATED, UPDATER) VALUES ('2번', '2번 회의실', null, true, now(), 'admin', now(), 'admin');

INSERT INTO TBL_MEETING_ROOM (NAME, DESCRIPTION, ONLINE_URL, USE_YN, CREATED, CREATOR, UPDATED, UPDATER) VALUES ('3번', '3번 회의실', null, true, now(), 'admin', now(), 'admin');

INSERT INTO TBL_MEETING_ROOM (NAME, DESCRIPTION, ONLINE_URL, USE_YN, CREATED, CREATOR, UPDATED, UPDATER) VALUES ('4번', '4번 회의실', null, true, now(), 'admin', now(), 'admin');

잘 들어갔나 볼까?

SELECT * FROM TBL_MEETING_ROOM;

음~ 퍼펙 ✨

express 에 데이터베이스 연동하기

이제 본격적으로 express 에 이어붙여보자.
우선 npm의 mysql 패키지를 설치해주어야 한다.

npm install --save mysql

설치 뒤backend/database.js 파일 생성!

const mysql = require('mysql');

const connection = mysql.createConnection({
  host     : 'localhost',
  user     : '아이디',
  password : '비밀번호',
  database : 'neti'
});

connection.connect();

module.exports = connection;

백엔드 구조 짜는데 익숙하지 않아서 일단 다 때려넣었다.

이렇게 만든 mysql 커넥션을 app.js 에서 사용하게 해주어야겠지?
backend/app.js 오픈

const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');

// router
const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');
const meetingroomsRouter = require('./routes/meetingrooms');

// db
// import connection from './database';
const connection = require('./database');

const app = express();

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
// ui 안쓰니까 생략한다
// app.use(express.static(path.join(__dirname, 'public')));

// samples
app.use('/', indexRouter);
app.use('/users', usersRouter);

// meetingroom
app.use('/meetingrooms', meetingroomsRouter);

module.exports = app;

이제 새로 추가하게 될 회의실 라우터(meetingroomsRouter)도 미리 추가해주었다.
기본으로 있던 샘플들도 일단 두자.

backend/routes/meetingrooms.js 파일을 새로 만들자.
연결 테스트 단계이므로 READ(=GET) 만 만들어보겠다.

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

const connection = require('../database');
// import connection from '../database';

// connection.connect();

/* GET meetingrooms listing. */
router.get('/', function(req, res, next) {

  // 쿼리 날려서 가져오기
  connection.query('SELECT * from TBL_MEETING_ROOM', (error, rows, fields) => {
    if (error) {
      console.error(error);
      res.status(500).send('Internal Server Error');
    }

    console.log(': ', rows);
    res.send(rows);
  });
});

module.exports = router;

쓰다보니 es6 문법이 안먹히더라... 내일은 이걸 해야겠다 마음먹으면서 npm run start 명령어로 서버를 띄우자.

테스트용이니까 거창하게 포스트맨을 띄우지 않고 curl 로 테스트하자.

curl -v http://localhost:5051/meetingrooms | json_pp

굿! 잘 나온당🍻

이제 CRUD 테스트

사실 의미가 없긴 하지만 이왕 R을 만든김에 CUD도 같이 만들어두자.

Create (POST)

/* POST meetingrooms listing. */
router.post('/', function(req, res, next) {
  const params = req.body;
  const query = `INSERT INTO TBL_MEETING_ROOM (NAME, DESCRIPTION, ONLINE_URL, USE_YN, CREATED, CREATOR, UPDATED, UPDATER) VALUES
  ('${params.name}', '${params.description}', '${params.onlineUrl}', 1, now(), 'admin', now(), 'admin');`;

  console.log('[POST] meetingrooms query: ', query);

  connection.query(query, (error, result) => {
    if (error) {
      console.error(error);
      res.status(500).send('Internal Server Error');
    }

    console.log('[POST] meetingrooms result: ', result);

    if (Number.isNaN(result.insertId) || result.insertId < 0) {
      res.status(500).send('Item create failed.');
    }

    res.send({
      id: result.insertId,
    });
  });
});

Update (PUT)

/* PUT meetingrooms listing. */
router.put('/:id', function(req, res, next) {
  if (!req.params.id) {
    res.status(500).send('Id is not exist.');
    return;
  }

  const params = req.body;
  const query = `UPDATE TBL_MEETING_ROOM SET ${Object.keys(params).map(key => `${key} = '${params[key]}'`).join(',')}, updated = now() WHERE id = ${req.params.id};`;

  console.log('[PUT] meetingrooms query: ', query);

  connection.query(query, (error, result) => {
    if (error) {
      console.error(error);
      res.status(500).send('Internal Server Error');
    }

    console.log('[PUT] meetingrooms result: ', result);

    res.send({});
  });
});

Delete (DELETE)

/* DELETE meetingrooms listing. */
router.delete('/:id', function(req, res, next) {
  if (!req.params.id) {
    res.status(500).send('Id is not exist.');
    return;
  }

  const query = `DELETE FROM TBL_MEETING_ROOM WHERE id = ${req.params.id};`;
  console.log('[DELETE] meetingrooms query: ', query);

  connection.query(query, (error, result) => {
    if (error) {
      console.error(error);
      res.status(500).send('Internal Server Error');
    }

    console.log('[DELETE] meetingrooms result: ', result);

    res.send({});
  });
});

테스트는 포스트맨으로 대충 완료함.


이로써 백이랑 프론트의 기초 공사는 다 했다.

내일은 backend 소스도 es6를 사용할 수 있도록 babel을 추가하고, API 호출 시 사용되는 response /request 에 일정한 규칙을 부여해서 객체화 할 예정이다.😊

좀 더 우아한 소스를 쓸 수 있게 공부도 더 해야겠다 💪✨

profile
안녕나는클레오파트라세상에서제일가는포테이토칩
post-custom-banner

0개의 댓글