Blog

[Node.js] 6. Bodyparser사용 및 MySQL2, dotenv 미들웨어로 DB연결하기(CRUD-Create 기능)

Category
Author
citeFred
citeFred
PinOnMain
1 more property
body-parser, MySQL2 미들웨어
Table of Content

데이터 요청의 body-parser 필요

우선 프론트엔드에서 문의하기 부분의 다음 코드로 기본적인 데이터 요청을 테스트하고자 한다.
contact.ejs
<%-include('layouts/header.ejs')%> <h2>문의하기</h2> <form action="/api/contact" method="post"> <ul> <li>이름 : <input type="text" name="name" required></li> <li>연락처 : <input type="text" name="phone" required></li> <li>이메일 : <input type="text" name="email" required></li> <li>내용 : <br> <textarea name="memo" cols="50" rows="10"></textarea> </li> <button type="submit">문의하기</button> </ul> </form> <%-include('layouts/footer.ejs')%>
JavaScript
복사
Frontend 커밋 이후 → master 체크아웃 → 현재까지 변동사항 master로 병합 (git merge Frontend)
또는 GUI로 Merge
이후 Backend는 커밋이 뒤처져있으므로 Backend 체크아웃 → 변동사항 적용 (git rebase master)
app.js에서 위 form의 요청을 받고 응답을 보낼 라우터를 아래와 같이 작성하고 서버를 실행해둔다.
app.post('/api/contact', (req, res) => { const name = req.body.name; const phone = req.body.phone; const email = req.body.email; const memo = req.body.memo; const data = `${name} ${phone} ${email} ${memo}` res.send(data); })
JavaScript
복사
위 작성된 문의하기 폼을 통해서 각 필드값들 form을 통해 post 요청할 수 있다.
특히 단순한 조회 이외 작성, 수정, 삭제 등은 POST요청으로 해야 Payload에 데이터를 은닉하여 전송 할 수 있다. get요청과 다르게 request의 body에서 데이터를 보내게 된다. 하지만 애초에 body.name 자체를 읽어내지 못하게 된다.
또는, 아래와 같이 나타난다.
이때 다음과 같이 데이터가 비정상적으로 읽히게 된다. Express.js는 기본적으로 요청의 본문을 파싱해주지 않기 때문에 body-parser를 사용하면 쉽게 요청 데이터에 접근할 수 있다.

body-parser 설치

npm install body-parser
JavaScript
복사

어플리케이션에 body-parser 설정

Express앱 상단에 body-parser를 사용 할 수 있도록 선언해야 한다. 공식문서에는 아래 그림처럼 어플리케이션에서 body-parser를 적용 시키도록 안내되어 있다.
위 코드를 참고하여 프로젝트에 아래와 같이 코드를 적용했다.
const express = require('express') const ejs = require('ejs') const bodyParser = require('body-parser') const app = express() const port = 3000 app.set('view engine', 'ejs'); app.set('views', './views') // parse application/x-www-form-urlencoded app.use(bodyParser.urlencoded({ extended: false })) // parse JSON app.use(bodyParser.json())
JavaScript
복사
bodyPaser가 주로 HTML 폼에서 전송되는 데이터 형식인 application/x-www-form-urlencoded 를 처리, 광범위하게 사용되는 데이터 형식인 application/json 또한 처리하도록 설정
따라서 클라이언트가 보내는 데이터 형식에 맞춰 적절하게 파싱하여 req.body로 접근할 수 있게 됨
이후 아래와 같이 인풋필드에 데이터들을 입력하고 요청을 하면 response로 data에 할당한 변수들이 정상적으로 출력되는 것을 확인 할 수 있다.
POSTMAN 또한 정상적으로 작동한다.

Database에 넣어보기

로컬 환경의 MySQL 데이터베이스를 구축하고 프로젝트와 연결하고자 한다.

0. MySQL 환경 구축

로컬 환경 MySQL 설치는 위 문서를 참고하여 진행 할 수 있다. Windows 버전의 경우 보다 손쉽게 클라이언트를 공식 홈페이지를 통해 설치하여 사용 할 수 있다. 데이터베이스 GUI툴은 MySQL-Workbench 를 포함하여 수 없이 많이 있지만 DBeaver 또한 직관적이고 라이트하여 사용하기 편리하다.
데이터베이스 생성 이후 우선 CLI환경에서도 익숙해지는것도 필요하기 때문에 간단한 CLI로 진행하고자 한다.
우선 위 MySQL 로컬 데이터베이스 설치 및 실행이 완료되면 아래 과정을 진행한다.

1. MySQL2 미들웨어 설치

express에서 mysql과 연결하기 위해서는 mysql2 미들웨어를 설치해야 한다.
npm install mysql2
JavaScript
복사

2. mysql 커넥션 작성

mysql2를 설치하면 app.js에서 mysql을 사용 할 수 있도록 설정해주어야 한다.
const express = require('express') const ejs = require('ejs') const bodyParser = require('body-parser') const mysql = require('mysql2'); const app = express() const port = 3000 ... // MySQL connection const connection = mysql.createConnection({ host: "localhost", user: "inyongkim", password: "1234", port: 3306, database: "nodejs_sample", insecureAuth: true, });
JavaScript
복사
하지만 현재 app.js에서는 host, user, password 등 민감함 일부 사용자 정보등이 담기게 될 수 있고 github 등 원격 저장소를 통해서 공개되어 알수없는 사고가 발생 할 수 있다. 따라서 이런 민감한 정보들은 별도로 관리하고 참조하는 방법을 사용하는 것이 좋다.

3. dotenv를 사용하기

dotenv는 Node.js 애플리케이션에서 환경 변수를 로드하는 데 사용되는 미들웨어이다. 애플리케이션의 설정 정보, 비밀 키, API 토큰 등과 같은 중요한 데이터를 안전하게 저장하는 데 사용된다. DB 접속 정보 또한 사용자 계정, 비밀번호가 담기기 때문에 이를 활용하여 관리하는 것이 좋다.
npm install dotenv
JavaScript
복사

.env 파일 생성 및 정보 입력

아래처럼 각 정보들을 직접 입력해둔다.

.env 설정파일로 불러오기

app.js에서 해당 파일이 환경 변수가 담긴 것을 인식해야하고 로드 할 수 있어야 한다. 다음과 같이 설정 파일임을 선언한다.
require('dotenv').config();
JavaScript
복사
이후 app.js의 mysql 커넥션 코드는 다음처럼 변수명으로 대체하여 은닉할 수 있다.
// MySQL connection const connection = mysql.createConnection({ host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PW, port: process.env.DB_PORT, database: process.env.DB_NAME, insecureAuth: true, });
JavaScript
복사

.gitignore 추적 금지

하지만 아직 .env 파일 자체가 git 버전관리 파일에 포함되어 있으며 이것이 github로 전송되어 내용이 공개되게 된다. 따라서 .gitignore에 .env 파일을 추적 제외하여 업로드 할 수 없도록 한다.

4. mysql 데이터베이스 생성

이제 mysql2 미들웨어를 통해 어플리케이션은 mysql 데이터베이스와 연결되도록 설정되었다. 이제 mysql 데이터베이스에 테이블을 생성하여 작동을 확인해야 한다.
터미널을 통해서 mysql에 접근한다.
mysql -u {username} -p
JavaScript
복사
보통 DB계정이름은 root으로 되어있을 수 있으며 타 계정을 사용하는 경우 grant를 통해 테이블등 생성권한, 접근 권한등을 설정해주어야 한다.
show databases;
JavaScript
복사
데이터베이스 목록을 조회한다. 기본적으로 처음 설치해도 기본 샘플 데이터베이스들이 보여진다.
create database {dbname};
JavaScript
복사
원하는 이름의 데이터베이스를 생성한다. 그리고 다시 show databases; 로 조회하면 아래처럼 원하는 데이터베이스가 생성된 것을 확인 할 수 있다.

5. 테이블 생성

간단한 테이블을 생성하고자 한다. MySQL은 RDBMS로 스키마에 따라 데이터가 존재하게 되는데,
스키마란 테이블의 구조, 타입, 제약조건 등 정해진 틀, 설정이라고 생각하면 된다.
따라서 DB생성자는 이런 구조를 정확하게 먼저 생성해주게 되어 있으며 데이터는 그 스키마에 맞는 데이터들이 삽입되게 된다.
아래처럼 contact라는 테이블의 구조를 상세히 적어서 생성해준다.
CREATE TABLE IF NOT EXISTS contact ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), phone VARCHAR(20), email VARCHAR(255), memo TEXT, create_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, modify_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );
JavaScript
복사
이후 show tables;로 생성된 테이블을 살펴 볼 수 있다.
설정한 타입 및 제약조건등을 확인하기 위해서는 아래 명령어로 살펴 볼 수 있다.
DESC contact;
JavaScript
복사

6. POST 요청 보내보기

mysql 데이터베이스에 원하는 규격의 테이블이 생성되었으며, app.js에서는 mysql2 미들웨어로 커넥션을 구성하였다. 이제 app.post() 요청에서 정상적으로 데이터가 삽입되는지 확인해야 한다.
app.js의 전체적인 코드는 다음과 같다.
const express = require('express') const ejs = require('ejs') const bodyParser = require('body-parser') const mysql = require('mysql2'); require('dotenv').config(); const app = express() const port = 3000 app.set('view engine', 'ejs'); app.set('views', './views') // parse application/x-www-form-urlencoded app.use(bodyParser.urlencoded({ extended: false })) // parse JSON app.use(bodyParser.json()) // MySQL connection const connection = mysql.createConnection({ host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PW, port: process.env.DB_PORT, database: process.env.DB_NAME, insecureAuth: true, }); ... app.post('/api/contact', (req, res) => { const name = req.body.name; const phone = req.body.phone; const email = req.body.email; const memo = req.body.memo; const SQL_Query = `INSERT INTO contact(name, phone, email, memo, create_at, modify_at) VALUES ('${name}','${phone}','${email}','${memo}',NOW(), NOW())`; connection.query(SQL_Query, (err, result) => { if (err) { console.error('데이터 삽입 중 에러 발생:', err); res.status(500).send('내부 서버 오류'); } else { console.log('데이터가 삽입되었습니다.'); res.send("<script>alert('문의사항이 등록되었습니다.'); location.href='/'</script>"); } }); });
JavaScript
복사
contact 페이지에서 입력한 값들이 정상적으로 전송 되고 데이터베이스에도 INSERT문이 작동되어 저장된 것을 확인 할 수 있다.
select * from contact;
JavaScript
복사

7. 커넥션 풀로 변경하기

위 mysql 연결은 현재 단일 커넥션이다. 일반적으로 커넥션 풀을 사용하는 것이 단일 커넥션을 사용하는 것보다 일반적으로 더 효율적인데 그 이유는 다음과 같다.
1.
리소스 관리: 커넥션 풀을 사용하면 여러 클라이언트 간에 커넥션을 공유하고 미리 여러 개의 커넥션을 생성하고 풀에 저장해 놓기 때문에 기존의 커넥션을 재사용할 수 있음. 생성과 닫기 과정에 발생하는 지연이 감소하고, 전반적인 성능이 향상
2.
동시성 관리: 커넥션 풀을 사용하면 여러 요청이 동시에 처리될 때 커넥션을 효과적으로 관리하여 동시성 문제를 더 쉽게 다룰 수 있음
3.
애플리케이션 안정성: 커넥션 풀은 커넥션의 오류를 감지하고 이를 처리할 수 있는 기능을 제공함. 또한 메모리 누수와 같은 문제를 방지
따라서 위 커넥션 코드를 커넥션 풀로 관리되도록 리팩토링하였다.
const express = require('express') const ejs = require('ejs') const bodyParser = require('body-parser') const mysql = require('mysql2'); require('dotenv').config(); const app = express() const port = 3000 app.set('view engine', 'ejs'); app.set('views', './views') // parse application/x-www-form-urlencoded app.use(bodyParser.urlencoded({ extended: false })) // parse JSON app.use(bodyParser.json()) // MySQL connection Pool : // MySQL 커넥션을 사용할 때는 주로 커넥션 풀을 이용하여 관리하는 것이 권장 // 여러 요청이 동시에 처리될 때 효율적으로 커넥션을 관리 const connectionPool = mysql.createPool({ host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PW, port: process.env.DB_PORT, database: process.env.DB_NAME, connectionLimit: 10, // 최대 연결 수 설정 insecureAuth: true, }); // MySQL connection check connectionPool.getConnection((err, connection) => { if (err) { console.error('MySQL에 연결 중 에러 발생:', err); } else { console.log('MySQL에 연결되었습니다.'); connection.release(); } }); ...
JavaScript
복사
라우터 중 post요청 부분의 코드도 connectionPool을 통해서 진행되도록 수정하였다.
app.post('/api/contact', (req, res) => { const name = req.body.name; const phone = req.body.phone; const email = req.body.email; const memo = req.body.memo; const SQL_Query = `INSERT INTO contact(name, phone, email, memo, create_at, modify_at) VALUES ('${name}','${phone}','${email}','${memo}',NOW(), NOW())`; connectionPool.query(SQL_Query, (err, result) => { if (err) { console.error('데이터 삽입 중 에러 발생:', err); res.status(500).send('내부 서버 오류'); } else { console.log('데이터가 삽입되었습니다.'); res.send("<script>alert('문의사항이 등록되었습니다.'); location.href='/'</script>"); } }); });
JavaScript
복사
Search
 | Main Page | Category |  Tags | About Me | Contact | Portfolio