ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 제로부터 시작하는 Node.js - 13. MySQL 연결, CRUD 구현
    내가 보기 위해 쓰는 것/Node.js 2019. 11. 19. 19:41

    mysql 모듈을 사용해서 실제 데이터베이스인 MySQL과 연결해 데이터를 핸들링 하는 방법을 알아보겠습니다.

     

    mysql에 대한 기본 구문은 안다고 가정하겠습니다. 사실 저도 다 모르는데 필요할때 '뭐드라' 하면서 검색해보면서 씁니다. 뭐든 DB를 배우셨으면 됩니다.

     

    mysql 모듈을 설치해줍시다.

     

    npm install --save mysql

     

    이제 시작해봅시다.

     

    1. MySQL 모듈

    const mysql = require('mysql')

     

    mysql에서 주로 사용하는 메서드로 createConnection(options) 이 있습니다.

     

    데이터베이스에 접속하는 메서드입니다.

    options 자리에 입력해야하는 속성이 몇 있습니다. 그 중 user와 password는 필수입니다.

    아래 표에서 options 자리에 들어갈 속성을 정리했습니다.

     

    속성 설명
    host 연결할 호스트
    port 연결할 포트
    user db 계정
    password db 계정 비밀번호
    database 연결할 데이터베이스
    debug 디버그 모드를 사용할 지 여부

     

    기본적인 사용 법을 보시면 이해가 가시리라 생각합니다.

     

    const mysql = require('mysql')
    
    const client = mysql.createConnection({
      user: 'root',
      password: '비밀번호',
      database: 'Music'
    })
    
    client.query('SELECT * FROM AlbumList', function (err, result, fields) {
      if (err) {
        console.log('DB Query incorrect')
      } else {
        console.log(result)
      }
    })
    

     

    물론 지금 실행해도 DB Query incorrect라고 뜨겠죠, DB가 없어서 입니다.

    그냥 이런식으로 쓰이는 구나 하고 query 메서드 같은 것들의 사용법을 보시면 됩니다.

     

    2. CRUD 구현

    이제 CRUD를 구현해봅시다. CRUD는 (Create, Read, Update, Delete)의 약자로 데이터 핸들링에 관한 기본적인 기능을 구현하는 것이라고 생각하시면 될 것 같습니다.

     

    2-1. 데이터 만들기

    우선 데이터가 있어야 하겠죠. 적당한 데이터를 만듭시다. 

     

     

    저는 대강 이런식으로, exam01 데이터베이스에 MusicList라는 테이블을 만들고 데이터를 조금 넣었습니다.

     

    이제 진짜 시작합시다.

     

    2-2. CRUD 페이지 구현 - 리스트 출력

    이번에도 예제가 조금 깁니다. 리스트를 보여줄 페이지, 추가 페이지, 수정 페이지 세 개가 필요합니다.

    필요한 모듈은 express, ejs, mysql, body-parser 입니다.

    또, MySQL 8^ 버전을 사용하시는 분들은 Auth 모드를 Legacy로 해주셔야 똑같이 구현할 수 있습니다.

    만약 SQL Query에서 에러가 뜬다면 https://www.inflearn.com/questions/3637

    이 글혹은 https://stackoverflow.com/questions/44946270/er-not-supported-auth-mode-mysql-server

    스택오버플로우 첫번째 답변을 참고하시면 됩니다.

     

    index.js 입니다. 빈 곳은 차근차근 코드를 추가하면서 확인해보겠습니다.

     

    const express = require('express')
    const fs = require('fs')
    const ejs = require('ejs')
    const mysql = require('mysql')
    const bodyParser = require('body-parser')
    
    const client = mysql.createConnection({
      user: 'root',
      password: '비밀번호', //본인의 db root 계정 비밀번호
      database: 'exam01' //본인의 db
    })
    
    const app = express()
    
    app.use(bodyParser.urlencoded({
      extended: false
    }))
    
    app.listen(52273, function () {
      console.log('Server is running at : http://127.0.0.1:52273')
    })
    
    app.get('/', function (req, res) {
      fs.readFile('list.ejs', 'utf8', function (err, data) {
        client.query('select * from MusicList', function (err, results) {
          if (err) {
            res.send(err)
          } else {
            res.send(ejs.render(data, {
              data: results
            }))
          }
        })
      })
    })
    
    app.get('/delete/:id', function (req, res) {
      
    })
    
    app.get('/insert', function (req, res) {
    
    })
    
    app.post('/insert', function (req, res) {
    
    })
    
    app.get('/edit/:id', function (req, res) {
    
    })
    
    app.post('/edit/:id', function (req, res) {
    
    })
    

     

    list.ejs 입니다.

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>List Page</title>
    </head>
    <body>
      <h1>Music List</h1>
      <a href="/insert">Add Music</a>
      <hr/>
      <table border="1">
        <tr>
          <th>DELETE</th>
          <th>EDIT</th>
          <th>id</th>
          <th>Name</th>
          <th>Artist</th>
          <th>Genre</th>
        </tr>
        <% data.forEach(function (item, index) { %>
        <tr>
          <td><a href="/delete/<%= item.id%>">DELETE</a></td>
          <td><a href="/edit/<%= item.id %>">EDIT</a></td>
          <td><%= item.id %></td>
          <td><%= item.name %></td>
          <td><%= item.artist %></td>
          <td><%= item.genre %></td>
        </tr>
        <% }); %>
      </table>
    </body>
    </html>
    

     

    127.0.0.1:52273에 접속하면 저는 이런 결과가 나오네요.

     

    ejs의 사용법, 첫번째 get 메서드의 메커니즘은 이미 언급된 적 있으니 넘어가겠습니다.

    다만 데이터베이스에 접속한 후 select * from MusicList 라는 sql문으로 받은 데이터를 어떻게 처리했느냐가 핵심입니다.

    그냥 단순하게 res.send(resulsts) 를 하면 json 형식의 데이터가 나옵니다.

     

    그냥 이렇게하면...

     

    이런 결과가 나옵니다.

    이걸 ejs 매개변수로 대입시키고, ejs 에서 forEach문을 통해 나온 데이터 만큼 행이 추가된거죠.

     

    2-3. CRUD 페이지 구현 - 행 삭제

    이제 DELETE 기능을 구현해봅시다. app.get('/delete/:id'..~ 부분에 빈 곳의 코드입니다.

     

    app.get('/delete/:id', function (req, res) {
      client.query('delete from MusicList where id=?', [req.params.id], function () {
        res.redirect('/')
      })
    })
    

     

    'sql query에 ?가 들어간 곳은 뭔가요?'

    저건 ? 토큰이라고 합니다.

    sql query문을 쓸 때 조건같은 부분에 항상 유동적으로 값이 들어가야할 경우가 많습니다.

    그럴 때 ? 토큰을 넣고, 그 다음 매개변수에 배열로 값을 넣어주면 순서대로 대입되는 원리입니다.

     

    ejs 파일에 보면 이런 곳이 있었죠.

    <td><a href="/delete/<%= item.id %>">DELETE</a></td>
    

     

    바로 저길 클릭하면 /delete/행의id 로 get요청이 가겠죠?

    그러면 서버에서 그 id로 sql query delete문을 처리 한후 다시 리스트로 리다이렉트 시키는 그런 코드입니다.

    확인해봅시다.

     

    두번째 행의 DELETE를 누르니 행이 삭제되었습니다.

     

    2-4. CRUD 페이지 구현 - 데이터 추가

    데이터 추가는 실제 데이터베이스에 데이터가 추가되는 것을 의미합니다.

    그러니까 하나의 페이지가 더 필요합니다.

    또, GET 요청인가, POST 요청인가도 구분합니다. 그 이유는 add music을 눌렀을 때, 데이터 입력 양식페이지로 넘어 갈때 보내오는 GET요청, 데이터 입력 양식에서 데이터 추가 완료 버튼을 눌렀을때 보내올 POST 요청 두가지가 있기 때문입니다. 코드를 보시면 이해가 되실겁니다.

     

    INSERT DATA 버튼을 누르면 데이터 입력 양식페이지로 이동합니다.

    우선 'app.get('/insert', function...~ 빈 부분의 코드입니다.

     

    app.get('/insert', function (req, res) {
      fs.readFile('insert.html', 'utf8', function (err, data) {
        res.send(data)
      })
    })
    

     

    insert.html 입니다.

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>insert data</title>
    </head>
    <body>
      <h1>Add Music</h1>
      <hr/>
      <form method="post">
        <fieldset>
          <legend>Enter Music Data</legend>
          <table>
            <tr>
              <td><label>Name</label></td>
              <td><input type="text" name="name" /></td>
            </tr>
            <tr>
              <td><label>Artist</label></td>
              <td><input type="text" name="artist" /></td>
            </tr>
            <tr>
              <td><label>Genre</label></td>
              <td><input type="text" name="genre" /></td>
            </tr>
          </table>
          <input type="submit" value="Add It!">
        </fieldset>
      </form>
    </body>
    </html>
    

     

    이제 리스트 페이지에서 Add Music을 누르면

     

    이런 페이지로 가지겠죠. 다만 아직 작동하지 않습니다.

    POST 요청을 입력해줘야합니다.

     

    app.post('/insert', function (req, res) {~ 부분입니다.

     

    app.post('/insert', function (req, res) {
      const body = req.body
    
      client.query('insert into MusicList (name, artist, genre) values (?, ?, ?);', [
        body.name,
        body.artist,
        body.genre
      ], function() {
        res.redirect('/')
      })
    })
    

    POST 요청으로 받은 값을 그대로 query문에 넣고, 리다이렉트 한거네요.

     

    Add It! 을 누르면...

     

    추가되었습니다.

     

    2-5. CRUD 페이지 구현 - 데이터 수정

    데이터 수정입니다. 추가와 매우 유사하니 바로 소스를 보겠습니다.

     

    app.get('/edit/:id', function(req, res) { 부분입니다.

     

    app.get('/edit/:id', function (req, res) {
      fs.readFile('edit.ejs', 'utf8', function (err, data) {
        client.query('select * from MusicList where id = ?', [req.params.id], function (err, result) {
          res.send(ejs.render(data, {
            data: result[0]
          }))
        })
      })
    })
    

     

    edit.ejs입니다.

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Edit Music Data</title>
    </head>
    <body>
      <h1>Edit Music Info</h1>
      <hr/>
      <form method="post">
        <fieldset>
          <legend>Edit Music Info</legend>
          <table>
            <tr>
              <td><label>Id</label></td>
              <td><input type="text" name="id" value="<%= data.id %>" disabled /></td>
            </tr>
            <tr>
              <td><label>Name</label></td>
              <td><input type="text" name="name" value="<%= data.name %>" /></td>
            </tr>
            <tr>
              <td><label>Artist</label></td>
              <td><input type="text" name="artist" value="<%= data.artist %>" /></td>
            </tr>
            <tr>
              <td><label>Genre</label></td>
              <td><input type="text" name="genre" value="<%= data.genre %>" /></td>
            </tr>
          </table>
          <input type="submit" value="Submit!" />
        </fieldset>
      </form>
    </body>
    </html>
    

     

    역시 아직 post 요청부분을 작성하지 않았으니 작동하지 않을 것입니다.

    app.post('/edit/:id', function (req, res) { 부분입니다.

     

    app.post('/edit/:id', function (req, res) {
      const body = req.body
    
      client.query('update MusicList SET name=?, artist=?, genre=? where id=?',[
        body.name, body.artist, body.genre, req.params.id
      ], function () {
        res.redirect('/')
      })
    })
    

     

    이제 잘 되는지 확인해봅시다. 리스트중 하나를 골라 Edit을 누르면

     

    수정을 하고 Submit을 누릅시다.

     

    데이터 수정이 완료되었습니다. 

     

    모든 작업이 요청에 따라 작업 할 내용을 분리시켜놓고, 작업 할 내용에 따라 sql query문을 적절히 삽입해 주는 작업입니다. 

    당연하지만 실제 db를 확인해보아도 작업한 모든 것이 반영되있습니다.

     

     

    드디어 끝났습니다. 다음에는 express 프레임워크에 대해 알아봅시다.

    댓글

Designed by Tistory.