2019. 07. 15 수정
이번 글에서는 Node.js에서 MySQL을 연동하여 MySQL을 다루는 방법에 대해 알아보도록 하겠습니다.
개발 환경
express-generator : 스켈레톤 생성
Windows / MySQL 설치
WebStorm
1. MySQL 모듈
Node.js에서 MySQL을 사용하려면 mysql 모듈을 설치해야 합니다.
# npm install mysql
물론 윈도우 또는 리눅스 등에도 MySQL이 설치되어 있어야 합니다.
그래야 mysql 모듈의 createConnection() 메서드를 통해 MySQL과 커넥션을 맺을 수 있습니다.
createConnection(options) 메서드를 호출할 때, 인자로 커넥션과 관련된 DB 정보를 넘겨주는데, options에 부여할 수 있는 속성은 다음과 같습니다.
- host
- 연결할 호스트
- port
- 연결할 포트
- user
- 사용자 이름
- 필수 입력 값입니다.
- password
- 사용자 비밀번호
- 필수 입력 값입니다.
- database
- 연결할 데이터베이스
- debug
- 디버그 모드를 사용할 것인지
2. MySQL 커넥션
먼저 MySQL을 사용하기 전에, 필요한 데이터들을 시스템에 추가하도록 하겠습니다.
// 1. 데이터 베이스 생성 CREATE DATABASE mysqltest; // 2. products 테이블 생성 CREATE TABLE products( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, modelnumber VARCHAR(15) NOT NULL, series VARCHAR(30) NOT NULL ); // 3. 데이터 추가 INSERT INTO products (name, modelnumber, series) VALUES ("victolee", "1234", "1111");
다음으로 createConnection() 메서드를 호출하여 MySQL와 연동하는 코드를 작성해보도록 하겠습니다.
express-generator로 생성한 파일 중 /routes/index.js에서 아래와 같이 작성합니다.
/routes/index.js
const express = require('express');
const router = express.Router();
const mysql = require("mysql"); // mysql 모듈 require
// 커넥션 연결
let client = mysql.createConnection({
user: "root",
password: "비밀번호를 입력해주세요",
database: "mysqltest"
})
module.exports = router;
mysql 모듈객체의 createConnection() 메서드를 호출하여 반환된 객체를 client 변수에 할당합니다.
여기서 password 프로퍼티는 꼭 본인의 mysql 비밀번호를 입력해서 바꿔주셔야 합니다.
그러면 client 객체를 통해 쿼리를 작성할 수 있으며, 이는 뒤에서 살펴보도록 하겠습니다.
3. 데이터 조회 및 추가
이번에는 사용자가 HTML form 태그를 통해 데이터를 서버로 보냈을 때, 이 데이터를 받아 테이블에 추가하는 코드를 작성해보도록 하겠습니다.
먼저 views폴더에 create.ejs 파일을 생성하여 아래와 같이 HTML을 작성합니다.
/views/create.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<h1>목록 추가하기</h1>
<hr>
<form action="/create" method="POST">
<table>
<tr>
<td><input type="text" name="name" placeholder="이름을 입력하세요."></td>
</tr>
<tr>
<td><input type="text" name="modelnumber" placeholder="모델넘버를 입력하세요."></td>
</tr>
<tr>
<td><input type="text" name="series" placeholder="시리즈를 입력하세요."></td>
</tr>
</table>
<input type="submit" value="전송하기">
</form>
</body>
</html>
위와 같이 form 요소가 추가되어, "전송하기" 버튼을 누르면 /create 경로에 POST 방식으로 요청을 보내게 됩니다.
그 전에, create.ejs를 렌더링 해주는 GET 요청을 처리해주는 라우터가 필요하고,
product 테이블에 데이터를 추가해주는 POST 요청을 처리해주는 라우터가 필요합니다.
/routes/index.js 파일에 이에 대한 라우터 함수를 추가적으로 등록해주도록 하겠습니다.
/routes/index.js
router.get('/create', function(req, res, next) {
client.query("SELECT * FROM products;", function(err, result, fields){
if(err){
console.log(err);
console.log("쿼리문에 오류가 있습니다.");
}
else{
res.render('create', {
results: result
});
}
});
});
router.post('/create', function(req, res, next) {
var body = req.body;
client.query("INSERT INTO products (name, modelnumber, series) VALUES (?, ?, ?)", [
body.name, body.modelnumber, body.series
], function(){
res.redirect("/create");
});
});
create.ejs를 렌더링하는 GET 라우터는 쉽게 작성할 수 있습니다.
쿼리를 작성하는 방법은 query() 메서드를 호출하여 인자로 쿼리 내용을 작성하면 됩니다.
GET 라우터 함수는 products 테이블의 모든 상품을 조회하여, 웹 페이지에 JSON으로 반환하는 코드입니다.
POST 방식의 데이터는 req.body를 통해 가져올 수 있습니다.
( Express 4부터는 body-parser가 내장 모듈로 등록되어 있네요. )
input 요소의 name 속성을 통해 POST 데이터를 가져올 수 있습니다.
예를 들어, body.name, body.modelnumber, body.series는 input태그의 각 name입니다.
이 때, 사용자가 어떤 입력 값을 전달할지 모르기 때문에 INSERT 쿼리를 작성 할 때 ? 키워드를 사용합니다.
각각의 ?는 client.query() 메서드의 두 번째 파라미터인 배열의 각 원소( input 태그의 각 name 속성 )가 대응되며,
어떤 column에 들어갈 것인지는 VALUES 앞에 있는 칼럼에 대응되어 값이 저장됩니다.
예를 들어, name 컬럼에는 body.name이 저장됩니다.
실제로 데이터가 잘 들어가는지 테스트하기 위해 브라우저에서 http://localhost:3000/create 으로 접속해서 데이터를 전송한 후,
DB에서 products 테이블을 조회하면 데이터가 추가된 것을 확인할 수 있습니다.
*** Error ***
ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
서버 실행시 위와 같은 에러가 발생한다면, MySQL에서 아래의 명령어를 실행하면 해결됩니다. ( 참고 링크 )
아마 MySQL 버전이 8.x일 때 발생하는 문제 같습니다.
# ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '새로운 비밀번호';
# flush privileges;
4. products 목록 조회
이번에는 products 테이블에 있는 모든 데이터를 응답해보도록 하겠습니다.
먼저 응답 객체에서 nbsp;res.render() 메서드를 호출할 때 쿼리 결과를 클라이언트로 전송하기 위해,
/routes/index.js 파일에서 위에서 작성한 "/create" 경로 라우터 미들웨어를 아래와 같이 수정합니다.
/routes/index.js
router.get('/create', function(req, res, next) {
client.query("SELECT * FROM products;", function(err, result, fields){
if(err){
console.log("쿼리문에 오류가 있습니다.");
}
else{
res.render('create', {
results: result
});
}
});
});
render() 메서드를 호출 할 때, 쿼리 결과인 products 테이블의 모든 데이터를 콜백 함수에 result 인자로 넘겨주었습니다.
result에는 products 테이블의 데이터들이 배열의 형태로 담겨있습니다.
다음으로 데이터들을 반복문으로 조회하기 위해, /views/create.ejs 파일의 </form> 태그 아래에 아래의 코드를 추가합니다.
/views/create.ejs
<table>
<% for(let data of results) { %>
<tr>
<td><%= data.name %></td>
<td><%= data.modelnumber %></td>
<td><%= data.series %></td>
</tr>
<% } %>
</table>
이전처럼 테스트를 해보면, 반복문을 돌면서 조회가 잘 된다는 것을 확인할 수 있습니다.
이상으로 MySQL을 연동하여 데이터 조회, 추가 쿼리를 작성해보았습니다.
이 글에서 작성한 /route/index.js 파일의 코딩은 별로 바람직하지 않습니다.
DB 관련 설정 파일은 config 폴더를 만들어서 관리하는 것이 좋으며, 커넥션 풀 등 고려해야 할 것들이 많이 있습니다.
단지, 이런 식으로 MySQL 모듈을 사용한다는 점만 이해하시면 좋을 것 같네요.
참고로 query를 작성하는 것 말고, ORM을 이용하여 직관적인 메서드를 통해 DB 작업을 할 수 있습니다.
Node.js에서는 대표적으로 sequelize 라는 모듈을 통해 구현할 수 있는데, 이 모듈을 사용하면 코드가 간결해지고, 생산성이 높아집니다.
다음 글에서는 sequelize에 대해 알아보도록 하겠습니다.
'웹 프로그래밍 > Node.js' 카테고리의 다른 글
[Node.js] sequelize(3) - CRUD + RESTful 게시판 만들기 (7) | 2017.11.08 |
---|---|
[Node.js] sequelize(2) - 모델 정의하기 (4) | 2017.11.06 |
[Node.js] Sequelize(1) - sequelize와 sequelize-cli (8) | 2017.11.06 |
[Node.js] express-generator (2) - 폴더 및 파일 역할 (4) | 2017.11.04 |
[Node.js] express-generator (1) - express-generator와 미들웨어 개념 (12) | 2017.11.04 |
[Node.js] module 사용하기 (2) | 2017.10.11 |
[Node.js] 설치 및 Hello World 출력 (0) | 2017.10.11 |