NodeJS 101 โ ํํธ 2 MySQL
Source: Dev.to
์์ ์ ๊ณต๋ ์์ค ๋งํฌ ์ธ์ ๋ฒ์ญํ ํ ์คํธ๊ฐ ํฌํจ๋์ด ์์ง ์์ต๋๋ค. ๋ฒ์ญ์ ์ํ๋ ์ ์ฒด ๋ด์ฉ์ ์ ๊ณตํด ์ฃผ์๋ฉด ํ๊ตญ์ด๋ก ๋ฒ์ญํด ๋๋ฆฌ๊ฒ ์ต๋๋ค.
๐ ์๋ฌธ
์ด ๋ฌธ์๋ web service ๋๋ RESTful API ๋ฅผ JavaScript (Node.js) ์ธ์ด๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ ์์ํฌ์ ๋ค์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํจ๊ป ๊ฐ๋ฐํฉ๋๋ค.
- ๐ Express โ HTTP ํ๋ ์์ํฌ๋ก ์น ์๋ฒ๋ฅผ ์์ฑํฉ๋๋ค
- ๐๏ธ Sequelize โ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ด๋ฆฌ๋ฅผ ์ํ ORM
- ๐พ MySQL โ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค
- ๐ง POSTMAN โ API ํ ์คํธ ๋๊ตฌ
๐ ๋ชฉ์ฐจ
Module 2: ๐พ Basic API MySQL
Express์ MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ๋ฐ ์ฌ์ฉ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋๋ค
Section 2โ1 โ ๐ ์ Express ๋ฐ MySQL ์ฑ ๋ง๋ค๊ธฐ
๐ ์ ํ๋ก์ ํธ ๋ง๋ค๊ธฐ
-
ํด๋
demo-mysql๋ง๋ค๊ธฐmkdir demo-mysql -
demo-mysqlํด๋๋ก ์ด๋cd demo-mysqlโ ๏ธ ์ฃผ์: ์๋ณธ ๋ฌธ์์ ๋์ ์๋
cd mkdir demo-mysql๋ช ๋ น์ ์๋ชป๋์์ต๋๋ค. ํด๋๋ฅผ ๋ง๋ ํ์๋cd demo-mysql์ ์ฌ์ฉํด์ผ ํฉ๋๋ค -
Node.js ์ ํ๋ฆฌ์ผ์ด์ ๋ง๋ค๊ธฐ
npm init -y์ด ๋ช ๋ น์
package.jsonํ์ผ์ ์๋์ผ๋ก ์์ฑํฉ๋๋ค
๐ index.js ํ์ผ ๋ง๋ค๊ธฐ
const express = require('express');
const cors = require('cors'); // โ
cors ํจํค์ง๋ฅผ ์ฌ์ฉํ๊ณ require('express') ๋์ ์ฌ์ฉ
const PORT = process.env.PORT || 5000;
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.listen(PORT, () => {
console.log(`CORS enabled server listening on ${PORT}`);
});
โ ๏ธ ์ฃผ์: ๊ธฐ์กด ์ฝ๋์์๋ cors์ require('express')๋ฅผ ์ฌ์ฉํ๋๋ฐ ์ด๋ ์ฌ๋ฐ๋ฅด์ง ์์ต๋๋ค. require('cors')๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค
๐ฆ ํ์ํ ํจํค์ง ์ค์น
์ฃผ์ ํจํค์ง
npm install express mysql2 cors --save
๊ฐ๋ฐ ์์กด์ฑ โ Nodemon
npm install -D nodemon
์ ์ญ์ผ๋ก ์ค์นํ๊ณ ์ถ๋ค๋ฉด (์ ํ ์ฌํญ)
npm install -g nodemon
๐ ์ค์น๋ ํจํค์ง
| Package | Description |
|---|---|
express | Node.js์ฉ ์น ํ๋ ์์ํฌ |
mysql2 | Node.js์ฉ MySQL ํด๋ผ์ด์ธํธ |
cors | CrossโOrigin Resource Sharing์ ์ฒ๋ฆฌํ๋ ๋ฏธ๋ค์จ์ด |
nodemon | ํ์ผ ๋ณ๊ฒฝ ์ ์๋ฒ ์๋ ์ฌ์์ |
Section 2โ2 โ ๐ MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ
๐ฆ MySQL2 ๊ฐ์ ธ์ค๊ธฐ
๋ค์ ์ค์ index.js ํ์ผ์ ์ถ๊ฐํฉ๋๋ค
const mysql = require('mysql2');
๐ MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ
๋ฐฉ๋ฒ 1 โ ์์ ์ฌ์ฉ
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'basic_api_express_db'
});
๋ฐฉ๋ฒ 2 โ ํ๊ฒฝ ๋ณ์ ์ฌ์ฉ (์ถ์ฒ) โญ
const connection = mysql.createConnection({
host: process.env.DB_HOSTNAME || 'localhost',
user: process.env.DB_USERNAME || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_DATABASE || 'basic_api_express_db'
});
๐ก ์ถ์ฒ: ๋ฐฐํฌ ์ ๋ณด์๊ณผ ์ ์ฐ์ฑ์ ์ํด ๋ฐฉ๋ฒ 2๋ฅผ ์ฌ์ฉํ์ธ์
๐ฅ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ํ ์คํธ
๋ค์ ์ฝ๋๋ฅผ index.js์ ์ถ๊ฐํฉ๋๋ค
// Get all users
app.get('/users', (req, res) => {
try {
connection.query('SELECT * FROM `users`', (err, results) => {
if (err) {
return res.status(500).json({ message: "Database error", error: err });
}
res.status(200).json(results);
});
} catch (error) {
res.status(400).json({ message: "Get users failed", error: error.message });
}
});
// Get user by id
app.get('/users/:id', (req, res) => {
try {
const id = req.params.id;
connection.query(
'SELECT * FROM `users` WHERE `id` = ?',
[id],
(err, results) => {
if (err) {
return res.status(500).json({ message: "Database error", error: err });
}
if (results.length === 0) {
return res.status(404).json({ message: "User not found" });
}
res.status(200).json({ payload: results });
}
);
} catch (error) {
res.status(400).json({ message: "Get user by id failed", error: error.message });
}
});
๐งช API ํ ์คํธ
GET http://localhost:5000/users
GET http://localhost:5000/users/1
Section 2โ3 โ โ ์ฌ์ฉ์ ์์ฑ
(๋ด์ฉ์ด ์์ง ์ง์ ๋์ง ์์ โ ํ์์ ๋ฐ๋ผ ์ฝ๋์ ์ค๋ช ์ ์ถ๊ฐํ์ธ์)
Section 2โ4 โ โ๏ธ ์ฌ์ฉ์ ์ ๋ฐ์ดํธ
(๋ด์ฉ์ด ์์ง ์ง์ ๋์ง ์์ โ ์ฝ๋์ ์ค๋ช ์ ์ถ๊ฐํ์ธ์)
Source: โฆ
เธญเธเธดเธเธฒเธขเธเนเธญเนเธเธเธตเนเธเธฒเธกเธเนเธญเธเธเธฒเธฃ)*
Section 2โ5 โ ๐๏ธ DELETE USER
(เนเธเธทเนเธญเธซเธฒเธขเธฑเธเนเธกเนเนเธเนเธฃเธฐเธเธธ โ เนเธชเนเนเธเนเธเนเธฅเธฐเธเธณเธญเธเธดเธเธฒเธขเธเนเธญเนเธเธเธตเนเธเธฒเธกเธเนเธญเธเธเธฒเธฃ)
เธซเธกเธฒเธขเนเธซเธเธธ: เธซเธฒเธเธเนเธญเธเธเธฒเธฃเนเธเธดเนเธกเธชเนเธงเธเธเธญเธเธเธฒเธฃเธชเธฃเนเธฒเธ, เนเธเนเนเธ, เนเธฅเธฐเธฅเธเธเธนเนเนเธเน เนเธซเนเธเธณเธเธฒเธกเธฃเธนเธเนเธเธเธเธญเธ GET /users เนเธฅเธฐ GET /users/:id เนเธเธขเนเธเน INSERT, UPDATE, DELETE เธเนเธฒเธ connection.query เธเธฃเนเธญเธกเธเธฑเธเธเธฒเธฃ error handling เธญเธขเนเธฒเธเนเธเธตเธขเธงเธเธฑเธ.
๋ฒ์ญ
๋ค์์ ํ์์ ๋ฐ๋ผ ์ค๋ช ํ์ญ์์ค)*
Section 2โ5 โ ๐๏ธ DELETE USER
(๋ด์ฉ์ด ์์ง ์ง์ ๋์ง ์์ โ ํ์์ ๋ฐ๋ผ ์ฝ๋์ ์ค๋ช ์ ์ฝ์ ํ์ญ์์ค)
์ฐธ๊ณ : ์ฌ์ฉ์ ์์ฑ, ์์ , ์ญ์ ๋ถ๋ถ์ ์ถ๊ฐํ๋ ค๋ฉด GET /users ๋ฐ GET /users/:id ํ์์ ๋ฐ๋ผ INSERT, UPDATE, DELETE๋ฅผ connection.query๋ฅผ ํตํด ์ฌ์ฉํ๊ณ ๋์ผํ ์ค๋ฅ ์ฒ๋ฆฌ ๋ฐฉ์์ ์ ์ฉํ์ญ์์ค.
5000/users/1
Section 2โ3 โ โ CREATE USER
โ ์ User ๋ง๋ค๊ธฐ
ํ์ผ์ ์ถ๊ฐ: index.js
app.post('/users', (req, res, next) => {
try {
const { fname, lname, username, password, avatar } = req.body;
connection.query(
'INSERT INTO `users`(`fname`, `lname`, `username`, `password`, `avatar`) VALUES (?, ?, ?, ?, ?)',
[fname, lname, username, password, avatar],
(err, results) => {
if (err) {
return res.status(500).json({
message: "create user was failed",
error: err.message
});
}
res.status(201).json({
message: "create user was successfully",
payload: results
});
}
);
} catch (error) {
res.status(400).json({
message: "create user was failed",
error: error.message
});
}
});
๐ ์ฝ๋ ์ค๋ช
INSERT INTOโ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ๋ SQL ๋ช ๋ น?โ SQL ์ธ์ ์ ๋ฐฉ์ง๋ฅผ ์ํ ํ๋ ์ด์คํ๋status(201)โ ๋ฐ์ดํฐ ์์ฑ ์ฑ๊ณต์ ๋ํ๋ด๋ HTTP ์ํ ์ฝ๋
๐งช API ํ ์คํธ
POST http://localhost:5000/users
Content-Type: application/json
{
"fname": "John",
"lname": "Doe",
"username": "johndoe",
"password": "password123",
"avatar": "https://example.com/avatar.jpg"
}
Section 2โ4 โ โ๏ธ UPDATE USER
โ๏ธ User ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ
ํ์ผ์ ์ถ๊ฐ: index.js
app.put('/users/:id', (req, res, next) => {
try {
const id = req.params.id;
const { fname, lname, username, password, avatar } = req.body;
connection.query(
'UPDATE `users` SET `fname`= ?, `lname`= ?, `username`= ?, `password`= ?, `avatar`= ? WHERE id = ?',
[fname, lname, username, password, avatar, id],
(err, results) => {
if (err) {
return res.status(500).json({
message: "update user was failed",
error: err.message
});
}
if (results.affectedRows === 0) {
return res.status(404).json({
message: "User not found"
});
}
res.status(200).json({
message: "update user was successfully",
payload: results
});
}
);
} catch (error) {
res.status(400).json({
message: "update user was failed",
error: error.message
});
}
});
๐ ์ฝ๋ ์ค๋ช
UPDATEโ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธํ๋ SQL ๋ช ๋ นaffectedRowsโ ์ ๋ฐ์ดํธ๋ ํ ์ (0 = ๋ฐ์ดํฐ ์์)
๐งช API ํ ์คํธ
PUT http://localhost:5000/users/1
Content-Type: application/json
{
"fname": "Jane",
"lname": "Doe",
"username": "janedoe",
"password": "newpassword123",
"avatar": "https://example.com/new-avatar.jpg"
}
Section 2โ5 โ ๐๏ธ DELETE USER
๐๏ธ User ๋ฐ์ดํฐ ์ญ์
ํ์ผ์ ์ถ๊ฐ: index.js
app.delete('/users/:id', (req, res, next) => {
try {
const id = req.params.id;
connection.query(
'DELETE FROM `users` WHERE id = ?',
[id],
(err, results) => {
if (err) {
return res.status(500).json({
message: "delete user was failed",
error: err.message
});
}
if (results.affectedRows === 0) {
return res.status(404).json({
message: "User not found"
});
}
res.status(200).json({
message: "dele
Source:
te user was successfully",
payload: results
});
}
);
} catch (error) {
res.status(400).json({
message: "delete user was failed",
error: error.message
});
}
});
๐ ์ฝ๋ ์ค๋ช
DELETE FROMโ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๋ SQL ๋ช ๋ น์ดaffectedRowsโ ์ญ์ ๋ ํ ์ (0 = ๋ฐ์ดํฐ ์์)
๐งช API ํ ์คํธ
DELETE http://localhost:5000/users/1
๐ Module 2 ์์ฝ
์ฐ๋ฆฌ๋ Express์ MySQL Database๋ฅผ ์ฐ๊ฒฐํ๊ณ CRUD Operations๋ฅผ ๋ชจ๋ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ ์ต๋๋ค.
| Method | Endpoint | Description |
|---|---|---|
GET | /users | ๋ชจ๋ ์ฌ์ฉ์ ๋ฐ์ดํฐ ์กฐํ |
GET | /users/:id | ID์ ํด๋นํ๋ ์ฌ์ฉ์ ์กฐํ |
POST | /users | ์๋ก์ด ์ฌ์ฉ์ ์์ฑ |
PUT | /users/:id | ์ฌ์ฉ์ ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ |
DELETE | /users/:id | ์ฌ์ฉ์ ์ญ์ |
Reference