https://www.sitepoint.com/using-node-mysql-javascript-client/

이 튜토리얼에서는 자바 스크립트로 작성된 MySQL 용 Node.js 드라이버 인 mysql 모듈을 시작하는 방법을 살펴 본다. 저장 프로 시저를 검사하고 사용자 입력을 이스케이프하기 전에 모듈을 사용하여 MySQL 데이터베이스에 연결하고 일반적인 CRUD 작업을 수행하는 방법을 설명합니다.

이 인기있는 자습서는 2018 년에 업데이트되었습니다. 변경 사항에는 노드-mysql 모듈의 이름이 바뀌었고 초보자 용 지침이 추가되고 ORM에 섹션이 추가된다는 사실을 다루는 ES6 구문의 업데이트가 포함됩니다.

빠른 시작 : 노드에서 MySQL을 사용하는 방법

어쩌면 당신은 빠른 다리를 찾아 여기에 도착했습니다. 가능한 한 짧은 시간 안에 Node에서 MySQL을 시작하고 실행할 수있는 방법을 찾은 직후라면 우리가 살펴 보았습니다!

다음은 간단한 5 단계로 노드에서 MySQL을 사용하는 방법입니다.

  1. 새 프로젝트 만들기 : mkdir mysql-test && cd mysql-test
  2. package.json 파일을 만듭니다. npm init –y
  3. mysql 모듈을 설치한다 : npm install mysql –save
  4. app.js 파일을 만들고 아래 스 니펫에 복사하십시오.
  5. node app.js 파일을 실행하십시오. "Connected!"메시지를 관찰하십시오.
 //app.js const mysql = require('mysql'); const connection = mysql.createConnection({ host: 'localhost', user: 'user', password: 'password', database: 'database name' }); connection.connect((err) => { if (err) throw err; console.log('Connected!'); }); 

mysql 모듈 설치하기

이제 각 단계를 자세히 살펴 보겠습니다. 먼저, 명령 행을 사용하여 새 디렉토리를 작성하고 탐색합니다. 그런 다음 npm init –y 명령을 사용하여 package.json 파일을 만듭니다. -y 플래그는 npm이 기본값 만 사용하며 옵션을 묻지 않습니다.

이 단계에서는 노드와 npm이 시스템에 설치되어 있다고 가정합니다. 그렇지 않은 경우,이 SitePoint 기사를 통해이 작업을 수행하는 방법을 확인하십시오. nvm을 사용하여 여러 버전의 Node.js를 설치하십시오 .

그런 다음, npm에서 mysql 모듈 을 설치하고 프로젝트 종속성으로 저장합니다. 프로젝트 종속성 (dev 종속성과 반대)은 응용 프로그램을 실행하는 데 필요한 패키지입니다.이 두 가지의 차이점에 대한 자세한 내용은 여기를 참조하십시오 .

 mkdir mysql-test cd mysql-test npm install mysql -y 

npm을 사용하여 추가 도움이 필요하면 이 안내서 를 확인하거나 포럼에 질문하십시오.

시작하기

데이터베이스에 연결하기 전에 머신에 MySQL을 설치하고 구성해야합니다. 그렇지 않은 경우 해당 홈 페이지 의 설치 지침을 참조하십시오 .

다음으로해야 할 일은 작업 할 데이터베이스와 데이터베이스 테이블을 만드는 것입니다. phpMyAdmin 과 같은 그래픽 인터페이스를 사용하거나 명령 줄을 사용하여이 작업을 수행 할 수 있습니다. 이 기사에서는 sitepoint 라는 데이터베이스와 employees라는 테이블을 사용할 것이다. 다음은 데이터베이스의 덤프입니다. 따라하기를 원한다면 빠르게 시작할 수 있습니다.

 CREATE TABLE employees ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(50), location varchar(50), PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ; INSERT INTO employees (id, name, location) VALUES (1, 'Jasmine', 'Australia'), (2, 'Jay', 'India'), (3, 'Jim', 'Germany'), (4, 'Lesley', 'Scotland'); 

Node.js와 MySQL을 함께 사용하기 & mysql 자바 스크립트 클라이언트

데이터베이스에 연결하기

이제 mysql-test 디렉토리에 app.js 라는 파일을 만들고 Node.js에서 MySQL에 연결하는 방법을 살펴 보자.

 // app.js const mysql = require('mysql'); // First you need to create a connection to the db const con = mysql.createConnection({ host: 'localhost', user: 'user', password: 'password', }); con.connect((err) => { if(err){ console.log('Error connecting to Db'); return; } console.log('Connection established'); }); con.end((err) => { // The connection is terminated gracefully // Ensures all previously enqueued queries are still // before sending a COM_QUIT packet to the MySQL server. }); 

이제 터미널을 열고 node app.js 입력하십시오. 연결이 성공적으로 이루어지면 콘솔에 'Connection established'메시지가 표시되어야합니다. 뭔가 잘못된 경우 (예를 들어 잘못된 비밀번호를 입력하는 경우) JavaScript 오류 객체 ( err )의 인스턴스가 전달되는 콜백이 발생합니다. 이 정보를 콘솔에 기록하여 유용한 정보가 무엇인지 확인하십시오.

그루트를 사용하여 파일 변경 사항보기

우리가 코드를 변경할 때마다 수동으로 node app.js 를 실행하면 약간 지루해질 것이므로이를 자동화하겠습니다. 이 부분은이 튜토리얼의 나머지 부분과 함께 따라야 할 필요는 없지만 일부 키 스트로크를 확실히 저장합니다.

몇 가지 패키지를 설치해 보겠습니다.

 npm install --save-dev grunt grunt-contrib-watch grunt-execute 

Grunt 는 잘 알려진 JavaScript 작업 주자이고 grunt-contrib-watch 는 감시 된 파일이 변경 될 때마다 미리 정의 된 작업을 실행 하고 grunt-execute 는 node app.js 명령을 실행하는 데 사용될 수 있습니다.

설치가 끝나면 프로젝트 루트에 Gruntfile.js 라는 파일을 만들고 다음 코드를 추가하십시오.

 // Gruntfile.js module.exports = (grunt) => { grunt.initConfig({ execute: { target: { src: ['app.js'] } }, watch: { scripts: { files: ['app.js'], tasks: ['execute'], }, } }); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-execute'); }; 

이제 grunt watch 실행하고 app.js 변경 app.js . Grunt가 변경 사항을 감지하고 node app.js 명령을 다시 실행해야 node app.js .

쿼리 실행

독서

이제 Node.js에서 MySQL에 연결하는 방법을 알았으므로 SQL 쿼리를 실행하는 방법을 살펴 보자. 먼저 createConnection 명령에서 데이터베이스 이름 ( sitepoint )을 지정합니다.

 const con = mysql.createConnection({ host: 'localhost', user: 'user', password: 'password', database: 'sitepoint' }); 

연결이 설정되면 connection 변수를 사용하여 데이터베이스 테이블 employees 에 대한 쿼리를 실행합니다.

 con.query('SELECT * FROM employees', (err,rows) => { if(err) throw err; console.log('Data received from Db:\n'); console.log(rows); }); 

app.js ( grunt-watch 하거나 터미널에 node app.js 를 입력하여)를 실행하면 터미널에 기록 된 데이터베이스에서 반환 된 데이터를 볼 수 있습니다.

 [ { id: 1, name: 'Jasmine', location: 'Australia' }, { id: 2, name: 'Jay', location: 'India' }, { id: 3, name: 'Jim', location: 'Germany' }, { id: 4, name: 'Lesley', location: 'Scotland' } ] 

MySQL 데이터베이스에서 반환 된 데이터는 단순히 rows 객체를 반복하여 구문 분석 할 수 있습니다.

 rows.forEach( (row) => { console.log(`${row.name} is in ${row.location}`); }); 

생성

다음과 같이 데이터베이스에 대해 삽입 쿼리를 실행할 수 있습니다.

 const employee = { name: 'Winnie', location: 'Australia' }; con.query('INSERT INTO employees SET ?', employee, (err, res) => { if(err) throw err; console.log('Last insert ID:', res.insertId); }); 

콜백 매개 변수를 사용하여 삽입 된 레코드의 ID를 얻는 방법에 유의하십시오.

업데이트 중

마찬가지로 업데이트 쿼리를 실행하면 result.affectedRows 사용하여 영향을받는 행 수를 검색 할 수 있습니다.

 con.query( 'UPDATE employees SET location = ? Where ID = ?', ['South Africa', 5], (err, result) => { if (err) throw err; console.log(`Changed ${result.changedRows} row(s)`); } ); 

파괴

동일한 질문이 삭제 쿼리에 적용됩니다.

 con.query( 'DELETE FROM employees WHERE id = ?', [5], (err, result) => { if (err) throw err; console.log(`Deleted ${result.affectedRows} row(s)`); } ); 

고급 사용

mysql 모듈이 저장 프로 시저를 처리하고 사용자 입력을 이스케이프 처리하는 방법을 살펴보고 마무리하고 싶습니다.

저장 프로 시저

간단히 말하면, 저장 프로 시저 (stored procedure)는 데이터베이스 엔진과 연결된 프로그래밍 언어에 의해 호출 될 수있는 데이터베이스에 저장된 프로 시저 (예 : SQL로 작성된 프로 시저)입니다. 당신이 원기 회복을 필요로한다면 이 훌륭한 기사를 읽어보십시오.

모든 직원 세부 정보를 가져 오는 sitepoint 데이터베이스 용 저장 프로 시저를 만듭니다. 우리는 그것을 sp_getall 이라고 부를 것 sp_getall . 이렇게하려면 데이터베이스에 어떤 종류의 인터페이스가 필요합니다. phpMyAdmin을 사용하고 있습니다.sitepoint 데이터베이스에서 다음 쿼리를 실행합니다.

 DELIMITER $$ CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_getall`() BEGIN SELECT id, name, location FROM employees; END 

그러면 ROUTINES 테이블의 information_schema 데이터베이스에 프로 시저가 만들어지고 저장됩니다.

저장 프로 시저 phpMyAdmin

그런 다음 연결을 설정하고 연결 개체를 사용하여 다음과 같이 저장 프로 시저를 호출합니다.

 con.query('CALL sp_getall()',function(err, rows){ if (err) throw err; console.log('Data received from Db:\n'); console.log(rows); }); 

변경 사항을 저장하고 파일을 실행하십시오. 일단 실행되면 데이터베이스에서 리턴 된 데이터를 볼 수 있어야합니다.

 [ [ { id: 1, name: 'Jasmine', location: 'Australia' }, { id: 2, name: 'Jay', location: 'India' }, { id: 3, name: 'Jim', location: 'Germany' }, { id: 4, name: 'Lesley', location: 'Scotland' } ], { fieldCount: 0, affectedRows: 0, insertId: 0, serverStatus: 34, warningCount: 0, message: '', protocol41: true, changedRows: 0 } ] 

데이터와 함께 영향을받는 행 수, insertId 등의 추가 정보를 반환합니다. 반환 된 데이터의 0 번째 인덱스를 반복하여 직원 정보를 나머지 정보와 구분해야합니다.

 rows[0].forEach( (row) => { console.log(`${row.name} is in ${row.location}`); }); 

이제 입력 매개 변수가 필요한 저장 프로 시저를 고려해 보겠습니다.

 DELIMITER $$ CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_get_employee_detail`( in employee_id int ) BEGIN SELECT name, location FROM employees where id = employee_id; END 

이제 저장 프로 시저를 호출하는 동안 입력 매개 변수를 전달할 수 있습니다.

 con.query('CALL sp_get_employee_detail(1)', (err, rows) => { if(err) throw err; console.log('Data received from Db:\n'); console.log(rows[0]); }); 

대부분 레코드를 데이터베이스에 삽입하려고 할 때 마지막에 삽입 된 ID가 out 매개 변수로 반환되어야합니다. out 매개 변수를 사용하여 다음 삽입 저장 프로 시저를 고려하십시오.

 DELIMITER $$ CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_insert_employee`( out employee_id int, in employee_name varchar(25), in employee_location varchar(25) ) BEGIN insert into employees(name, location) values(employee_name, employee_location); set employee_id = LAST_INSERT_ID(); END 

out 매개 변수를 사용하여 프로 시저를 호출하려면 먼저 연결을 만드는 동안 여러 호출을 사용 가능하게 설정해야합니다. 따라서 다중 명령문 실행을 true 로 설정하여 연결을 수정하십시오.

 const con = mysql.createConnection({ host: 'localhost', user: 'user', password: 'password', database: 'sitepoint', multipleStatements: true }); 

다음으로 프로 시저를 호출 할 때 out 매개 변수를 설정하고 전달합니다.

 con.query( "SET @employee_id = 0; CALL sp_insert_employee(@employee_id, 'Ron', 'USA'); SELECT @employee_id", (err, rows) => { if (err) throw err; console.log('Data received from Db:\n'); console.log(rows); } ); 

위의 코드에서 볼 수 있듯이 out 매개 변수 @employee_id 설정하고 저장 프로 시저를 호출하는 동안이를 전달했습니다. 호출이 완료되면 반환 된 ID에 액세스하려면 out 매개 변수를 선택해야합니다.

app.js 실행하십시오. 성공적으로 실행되면 다양한 다른 정보와 함께 선택된 out 매개 변수를 볼 수 있어야합니다. rows[2] 는 선택된 out 매개 변수에 대한 액세스 권한을 제공해야합니다.

 [ { '@employee_id': 6 } ] 

사용자 입력 이스케이프

SQL 주입 공격을 피하기 위해서는 SQL 쿼리에서 사용하기 전에 항상 사용자 토지의 데이터를 이스케이프 처리해야합니다. 이유를 설명해 보겠습니다.

 const userLandVariable = '4 '; con.query( `SELECT * FROM employees WHERE id = ${userLandVariable}`, (err, rows) => { if(err) throw err; console.log(rows); } ); 

이것은 충분히 해가 없으며 올바른 결과를 반환합니다.

  { id: 4, name: 'Lesley', location: 'Scotland' } 

그러나 userLandVariable을 this로 변경하면 다음과 같이됩니다.

 const userLandVariable = '4 OR 1=1'; 

갑자기 전체 데이터 세트에 액세스 할 수 있습니다. 그런 다음 이것을 다음과 같이 변경하면 :

 const userLandVariable = '4; DROP TABLE employees'; 

그럼 우리는 적절한 문제에 처해있다!

좋은 소식은 도움이 가까이 왔다는 것입니다. mysql.escape 메소드를 사용하면된다.

 con.query( `SELECT * FROM employees WHERE id = ${mysql.escape(userLandVariable)}`, function(err, rows){ ... } ); 

또는 기사 시작 부분에있는 예제에서와 같이 물음표 자리 표시자를 사용합니다.

  con.query( 'SELECT * FROM employees WHERE id = ?', [userLandVariable], (err, rows) => { ... } ); 

왜 ORM을 사용하지 않는가?

아시다시피, 의견에있는 몇 사람이 ORM 사용을 제안하고 있습니다. 이 접근법의 장단점을 살펴보기 전에 ORM이 무엇인지 살펴 보겠습니다. 다음은 스택 오버플로에 대한 대답에서 가져온 것입니다.

ORM (Object-Relational Mapping)은 객체 지향 패러다임을 사용하여 데이터베이스의 데이터를 쿼리하고 조작 할 수있게 해주는 기술입니다. ORM에 대해 이야기 할 때, 대부분의 사람들은 Object-Relational Mapping 기술을 구현하는 라이브러리를 언급하고 있습니다. 따라서 "ORM"이라는 구절을 사용합니다.

그래서 기본적으로이 접근법은 ORM의 도메인 특정 언어로 데이터베이스 로직을 작성한다는 것을 의미합니다. 우리가 지금까지 수행해온 바닐라 접근 방식과 반대입니다.다음은 Sequelize 를 사용한 고안된 예제입니다.

 Employee.findAll().then(employees => { console.log(employees); }); 

대조 :

 con.query('SELECT * FROM employees', (err,rows) => { if(err) throw err; console.log('Data received from Db:\n'); console.log(rows); }); 

ORM 사용이 당신에게 의미가 있는지 여부는 당신이 작업하고있는 대상과 대상에 따라 크게 달라집니다. 한편으로 ORMS는 SQL의 상당 부분을 추상화하여 팀의 모든 사람들이 매우 효율적인 데이터베이스 관련 쿼리를 작성하는 방법을 알아야 할 필요가 없으므로 개발자의 생산성을 향상시키는 경향이 있습니다. 또한 다른 데이터베이스 소프트웨어로 쉽게 이동할 수 있습니다. 추상화로 발전하고 있기 때문입니다.

그러나 다른 한편으로는 ORM이하는 일을 이해하지 못해 실제로 복잡하고 비효율적 인 SQL을 작성하는 것이 가능합니다. ORM을 통과 할 필요가없는 쿼리를 최적화하는 것이 훨씬 쉽다는 점에서 성능 또한 문제가됩니다.

어떤 경로를 택 하느냐는 당신 에게 달려 있지만, 이것이 현재 진행중인 결정이라면이 스택 오버 플로우 스레드를 확인하십시오. 왜 ORM을 사용해야합니까? SitePoint에 대한이 게시물뿐만 아니라 3 가지 JavaScript ORM을 알 수 있습니다.

결론

이 튜토리얼에서 우리는 mysql 클라이언트가 제공하는 것의 표면만을 긁었다. 자세한 내용은 공식 문서를 읽는 것이 좋습니다. node-mysql2 및 node-mysql-libmysqlclient와 같은 다른 옵션도 있습니다.

Node.js에서 MySQL에 연결할 때 이러한 옵션을 사용 했습니까? 나는 그들을 듣는 것을 좋아할 것이다. 아래 의견에 귀하의 생각, 제안 및 수정 사항을 알려주십시오!