728x90

참고:

[MariaDB]설치하기

[MySQL]MySQL설치하기

[NodeJS]Window에서 설치하기

[NodeJS]nodejs프로젝트에 라이브러리 추가하기(npm)


NodeJS상에서 DB와 연동하는일은 너무 자주 있어서 자주있다고 말하기도 민망하다.

요즘 언어들이 모두 그렇듯이 nodejs도 연동하고 사용하는 일이 매우 간단하다.

이번에는 NodeJS와 MySQL(MariaDB)를 연동하도록 해보자.

MySQL이나 MariaDB나 연동하는 방식은 완전히 동일하므로 둘을 사용하는 사람은 크게 걱정할 필요가 없다고 생각이 된다.

예제는 express프레임워크위에서 실행하였다. none express라도 어느정도 참고할 수 있을 것이다.


먼저 실습을할 디렉터리 구조는 아래와 같다.



기본적으로 존재하는 users와 index를 제외하고 5개를 추가하였다.

각각의 예제의 역할은 아래와 같다.

또한 express에 라우팅해주었다.


show-all-data : select문을 사용하고 넘어오는 파라메터의 데이터를 확인하도록한다.

login : select문과 where절을 사용하고 pre-statment를 사용하는 법을 보도록한다.

join : insert문을 사용하도록 한다.

password-change : select문과 update문을 사용하도록 한다.

delete-account : select문과 delete문을 사용하도록한다.


제일 먼저 할일은 이제 npm을 이용하여서 mysql 커넥터를 설치하는 일이다.



npm instll mysql --save


설치가 끝나면 테스트를 할 db를 보도록하자.


테스트할 db는 필자의 경우 mydb라는 이름으로 만들었고 현재 두개의 데이터가 들어있다.

테이블의 이름은 test_user이다.

이중에서 id는 프라이머리키이다. 쿼리로 나타내면 아래와 같다.


create table test_user(
id varchar(30) primary key,
pw varchar(30)
);


이제 한 파트씩 만들어보고 테스트해보도록 하자.


show-all-data : selcet문 사용과 파라메터 확인

/*show-all-data.js*/
var express = require('express');
var router = express.Router();

var mysql = require('mysql');

router.get('/', function (req, res, next) {
var connection = mysql.createConnection({
host: 'localhost',
post: 3306,
user: 'root',
password: '',
database: 'mydb'
});
connection.connect();
connection.query('select * from test_user', function (err, rows, fields) {
connection.end();
if (!err) {
console.log(rows);
console.log(fields);
var result = 'rows : ' + JSON.stringify(rows) + '<br><br>' +
'fields : ' + JSON.stringify(fields);
res.send(result);
} else {
console.log('query error : ' + err);
res.send(err);
}
});
});

module.exports = router;

위의 show-all-data는 모든 데이터를 바로 문자열로 출력해줄것이다.

잘라서 부분부분 확인하도록 하자.


var mysql = require('mysql');

mysql모듈을 임포트시키므로 당연히 필요하다.


var connection = mysql.createConnection({
host: 'localhost',
post: 3000,
user: 'root',
password: '',
database: 'mydb'
});

이 부분으로 DB와 커넥션을 시켜준다. 아직 커넥션이 완료된건 아니고 커넥션을 해주는 부품을 만드는 것이다.


connection.connect();

여기서 위에 만든 커넥션에서 connect를 호출해주면 db가 연결된다.


connection.query('select * from test_user', function (err, rows, fields) {
if (!err) {
console.log(rows);
console.log(fields);
var result = 'rows : ' + JSON.stringify(rows) + '<br><br>' +
'fields : ' + JSON.stringify(fields);
res.send(result);
} else {
console.log('query error : ' + err);
res.send(err);
}
});

이부분에서 query를 실행한다. 쿼리를 실행하면 콜백함수에서 총 3개의 파라메터가 반환되는데 각각의 의미는 아래와 같다.


err - 에러가 판단했는지 여부이다. 에러가 일어났다면 어떤 에러인지도 알 수 있다.

rows - 쿼리의 실행결과 가지고 온 데이터이다.

fields - 쿼리의 실행결과 가지고 온 데이터들의 필드정보이다.


백문이 불여일견이라고 실행해보도록하자.


콘솔로 출력해본 값은 위와 같은 데이터를 받은 것을 확인할 수 있다.


또한 화면에 출력된 값으로 각각의 rows값과 각각의 fields값들이 넘어 온것을 확인할 수 있다.


connection.end();

마지막으로 커넥션의 연결을 끊어준다.

사실 커넥션은 칼같이 끊어야되는 경우가 아니라면(웹을사용한다면 칼같이 끊는일은 거의 없다.)

호출할 필요가 없다.


위의 코드는 전반적으로 DB를 호출해서 사용하는 방법에 대해서 논하고 있긴 하지만 문제점이 있다.

바로 호출할때마다 커넥션을 새로 만든다는 것이다.

이는 리소스도 리소스지만 에러를 야기할확률도 매우 높아진다.

물론 리소스 문제도 굉장히 심각하다.

따라서 전역으로 열어두는것이 낫다.

어짜피 연결을 한번하고 계속해서 호출하는게 낫기 때문이다.

그 방법을 한번 해보도록하자.


mysql-db라는 연결용 js파일을 만들었다.


var mysql = require('mysql');
var connection = mysql.createConnection({
host: 'localhost',
post: 3000,
user: 'root',
password: '',
database: 'mydb'
});

module.exports = connection;

이렇게 위와같이 모듈을 작성한다.


/*app.js*/
var mysqlDB = require('./mysql-db');
mysqlDB.connect();

/*source*/

app.js에서 만든 모듈을 호출해서 connect시킨다.


/*show-all-data.js*/
var express = require('express');
var router = express.Router();

var mysqlDB = require('../mysql-db');

router.get('/', function (req, res, next) {
mysqlDB.query('select * from test_user', function (err, rows, fields) {
if (!err) {
console.log(rows);
console.log(fields);
var result = 'rows : ' + JSON.stringify(rows) + '<br><br>' +
'fields : ' + JSON.stringify(fields);
res.send(result);
} else {
console.log('query error : ' + err);
res.send(err);
}
});
});

module.exports = router;

이제 mysql대신 우리가 만든 mysqlDB를 호출해준다.

만약 도중에 connect와 end를 동적이게 하고 싶다면 app.js에서 connect하지말고 각각의 router에서 해주면 된다.


login : select문과 where절을 사용


<!--login.ejs-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<h1>login</h1>
<form method="post">
<label>id :</label><input type="text" name="userId"><br>
<label>pw :</label><input type="password" name="userPw"><br>
<input type="submit">
</form>
</body>
</html>

일단 위와같이 렌더링 페이지를 만든다.

login 페이지를 get으로 들어갈 수도 있고 결과는 같은 페이지의 post로 보여주는 로직을 짜도록하자.


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

var mysql_db = require('../mysql-db');


router.get('/', function (req, res, next) {
res.render('login');
});

router.post('/', function (req, res, next) {
var userId = req.body['userId'];
var userPw = req.body['userPw'];
mysql_db.query('select * from test_user where id=\'' + userId + '\' and pw=\'' + userPw + '\'', function (err, rows, fields) {
if (!err) {
if (rows[0]!=undefined) {
res.send('id : ' + rows[0]['id'] + '<br>' +
'pw : ' + rows[0]['pw']);
} else {
res.send('no data');
}

} else {
res.send('error : ' + err);
}
});
});

module.exports = router;

커넥터는 이제 우리가만든 것을 사용할 것이다.

select구문에 where을 쓴 예시이다. 쿼리부분만 보도록 하자.


var userId = req.body['userId'];
var userPw = req.body['userPw'];
mysql_db.query('select * from test_user where id=\'' + userId + '\' and pw=\'' + userPw + '\'', function (err, rows, fields) {
if (!err) {
if (rows[0]!=undefined) {
res.send('id : ' + rows[0]['id'] + '<br>' +
'pw : ' + rows[0]['pw']);
} else {
res.send('no data');
}

} else {
res.send('error : ' + err);
}
});

파라메터를 req.body로 받아서 그 값을 직접 적어넣었다.

위의 결과가 제대로 작동하는지 확인해보도록하자.

만약 디비 커넥션이 제대로 되지 않는 다면 에러가 날것이다.

그다음 id와 비밀번호를 모두 확인해서 일치하는 값이 있다면 rows[0]가 존재(defined)할것이고 없다면 undefined할것이다.

위의 코드는 defined인지 undefined인지 확인후 존재한다면 id와 패스워드를 보여주게된다.


위는 로그인에 성공했을 때의 예시이다.


여기는 로그인에 실패했을 때의 예시이다.


위의 코드는 치명적인 문제점이 있다. 바로 파라메터를 직접넣기 때문에 sql인젝션이 될 위험성이 있다.

따라서 pre-statement로 처리하는것이 좋다.

아래는 pre-statemnet로 sql인젝션을 막게 만드는 코드이다.


mysql_db.query('select * from test_user where id=? and pw=?',[userId,userPw], function (err, rows, fields)

쿼리가 들어갈 부분을 ?로 대체해주고 두번째 파라메터로 콜백함수가 아닌 값을 리스트로 넣어주면된다.

코드를 작성하기도 훨씬 간편하며 sql인젝션을 방어할 수 있다.


join : insert문 사용


insert문으로 join을 구현해보도록하자.


<!--join.ejs-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Join</title>
</head>
<body>
<h1>join</h1>
<form method="post">
<label>id :</label><input type="text" name="userId"><br>
<label>pw :</label><input type="password" name="userPw"><br>
<label>pw-re :</label><input type="password" name="userPwRe"><br>
<input type="submit">
</form>
</body>
</html>

위와 같이 join페이지를 구현한다.

/*join.js*/
var express = require('express');
var router = express.Router();

var mysqlDB = require('../mysql-db');

router.get('/', function (req, res, next) {
res.render('join');
});

router.post('/', function (req, res, next) {
var userId = req.body['userId'];
var userPw = req.body['userPw'];
var userPwRe = req.body['userPwRe'];
if (userPw == userPwRe) {
mysqlDB.query('insert into test_user values(?,?)', [userId, userPw], function (err, rows, fields) {
if (!err) {
res.send('success');
} else {
res.send('err : ' + err);
}
});
}else{
res.send('password not match!');
}
});

module.exports = router;

위의 코드는 insert문을 사용한 예시이다.

if캐이스로 먼저 패스워드가 일치하는지를 확인한다.

일치하지 않을 경우 패스워드가 일치하지 않는 다고 알린다.

다음 if캐이스로는 해당 쿼리가 유효한 구문인지, 그리고 유효하게 작동하는지를 검사한다.

그럼 한번 만들어보도록 하자.


기존에 없던 새로운 아이디를 만들어보자.


비밀번호가 일치하며 기존에 존재하지 않는 아이디라면 성공하게된다.

실제 디비에서도 데이터가 적재된것을 확인할 수 있다.


이번에는 이미 존재하는 아이디로 다시만들려고 시도해보자.


그러면 아이디가 중복될 수 없다면서 에러가 뜬다.


password-change : select문과 update문 사용


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Password Change</title>
</head>
<body>
<h1>Password Change</h1>
<form method="post">
<label>id :</label><input type="text" name="userId"><br>
<label>pw :</label><input type="password" name="userPw"><br>
<label>pw-new :</label><input type="password" name="userPwNew"><br>
<input type="submit">
</form>
</body>
</html>

위와같이 코드를 작성한다.

이제 테스트를 하자.


//password-change.js
var express = require('express');
var router = express.Router();

var mysql_db = require('../mysql-db');


router.get('/', function (req, res, next) {
res.render('password-change');
});

router.post('/', function (req, res, next) {
var userId = req.body['userId'];
var userPw = req.body['userPw'];
var userPwNew = req.body['userPwNew'];
mysql_db.query('select * from test_user where id=? and pw=?', [userId, userPw], function (err, rows, fields) {
if (!err) {
if (rows[0] != undefined) {
mysql_db.query('update test_user set pw=? where id=?', [userPwNew, userId], function (err, rows, fields) {
if (!err) {
res.send('password change success');
} else {
res.send('error : ' + err);
}
});
} else {
res.send('no data');
}

} else {
res.send('error : ' + err);
}
});

});

module.exports = router;

코드가 좀 긴데 그 이유는 쿼리를 두번 쓰기 때문이다.

먼저 지금의 아이디와 패스워드가 맞는지를 확인하고 맞다면 패스워드를 변경해야하기 때문이다.

query의 콜백 안에 query를 쓰는 이유는 nodejs가 비동기식으로 데이터를 처리하기 때문이다.

저렇게 콜백을 쓰는게 귀찮다면 동기화시켜주는 모듈을 사용하면된다.

여기서 그걸 다루진 않겠다. 만약 동기화가 절실하다면 이 포스팅을 참조하라.

이제 제대로 작동하는지 테스트를 해보자.


아이디와 패스워드, 그리고 변경할 패스워드를 입력한다.


위와같이 패스워드가 변경된걸 확인할 수 있다.


delete-account : select문과 delete문을 사용


<!--delete-account.ejs-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Delete Account</title>
</head>
<body>
<h1>Delete Account</h1>
<form method="post">
<label>id :</label><input type="text" name="userId"><br>
<label>pw :</label><input type="password" name="userPw"><br>
<input type="submit">
</form>
</body>
</html>

위와 같이 코드를 작성한다.


//delete-account.js
var express = require('express');
var router = express.Router();

var mysql_db = require('../mysql-db');


router.get('/', function (req, res, next) {
res.render('delete-account');
});

router.post('/', function (req, res, next) {
var userId = req.body['userId'];
var userPw = req.body['userPw'];
mysql_db.query('select * from test_user where id=? and pw=?', [userId, userPw], function (err, rows, fields) {
if (!err) {
if (rows[0] != undefined) {
mysql_db.query('delete from test_user where id=?', [userId], function (err, rows, fields) {
if (!err) {
res.send('delete success');
} else {
res.send('error : ' + err);
}
});
} else {
res.send('no data');
}

} else {
res.send('error : ' + err);
}
});

});

module.exports = router;

위에서 다 설명 했기에 따로 설명할 코드는 없다. 실행해보자.


필자는 목록에 있는 ekekdid를 삭제했다.

제대로 됬는지 보자.


DB에서도 삭제된걸 확인할 수 있다.




+ Recent posts