React와 Node.js 연동을 해봤고 이제 MySQL까지 연동해보려고 한다.
이전글 : React와 Node.js 연동
MySQL workbench 설치 참고한 사이트
https://shinysblog.tistory.com/20
각각의 폴더 설명 (클라이언트가 요청을 했을 때, 처리 순서? 로 작성)
routes/
- 애플리케이션의 각 라우트를 정의
- 클라이언트의 요청은 Express 라우터에 의해 처리
- 요청이 들어온 경로와 HTTP 메소드에 따라 적절한 라우트 핸들러에 요청을 전달
controllers/
- HTTP 요청을 처리하는 라우트 핸들러들을 넣음
- 요청의 유효성을 검사하고 필요한 데이터를 가져오고 적절한 응답을 보내는 등의 작업을 수행
database/
- 데이터베이스 연결 설정이 있는 파일을 넣음
models/
- 데이터베이스와 관련된 코드를 저장
controllers
와 상호작용하여 데이터베이스 작업을 수행- 데이터를 가져오고, 생성하고, 업데이트하고, 삭제하는 기능을 포함
npm install mysql
// backend/database/db.js
const mysql = require('mysql');
const conn = mysql.createConnection({
host: 'localhost',
port: '포트번호',
user: 'user',
password: '비밀번호',
database: 'my_db'
});
conn.connect((err) => {
if (err) console.log(err);
else console.log('Connected to the database');
});
module.exports = conn;
// backend/server.js
const express = require('express');
const db = require('./database/db');
const app = express();
const port = 3001; // React의 포트 번호와 다르게 하기 위해
app.get('/', (req, res) => {
db.query('SELECT * FROM table_name', function (err, results, fields) {
if (err) throw err;
res.send(results);
});
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
테이블 생성
npm install bcrypt
// App.js
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Login from "./components/Login";
import Signup from './components/Signup';
import Main from './pages/Main';
function App() {
return (
<Router>
<Routes>
<Route path='/' element={<Login />}></Route>
<Route path='/signup' element={<Signup />}></Route>
<Route path='/main' element={<Main />}></Route>
</Routes>
</Router>
)
}
export default App;
// server.js
const express = require('express');
const cors = require("cors");
const userRoutes = require('./routes/userRoutes');
const app = express();
app.use(express.json());
app.use(cors({
origin: 'http://localhost:3000',
credentials: true,
}));
app.use('/api', userRoutes); // user 라우트 연결
app.listen(3001, () => {
console.log("서버 실행")
});
// userRoutes.js
const express = require('express');
const router = express.Router();
const userController = require('../controllers/user'); // 유저 컨트롤러 가져오기
router.post('/signup', userController.signup); // 회원가입 부분
router.post('/loginCheck', userController.loginCheck); // 로그인 부분
module.exports = router;
// db.js
const mysql = require('mysql');
const conn = mysql.createConnection({
host: 'localhost',
port: '포트번호',
user: 'user',
password: '비밀번호',
database: 'my_db'
});
conn.connect((err) => {
if (err) console.log(err);
else console.log('Connected to the database');
});
module.exports = conn;
// Signup.jsx
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
const Signup = () => {
const [id, setId] = useState('');
const [pw, setPw] = useState('');
const navigate = useNavigate();
const submitBtn = async () => {
if (id === '' || pw === '') {
alert("아이디 또는 비밀번호를 입력해주시기 바랍니다");
return;
} else {
try {
const res = await fetch('/api/signup', {
method: 'POST',
body: JSON.stringify({userID: id, userPW: pw}),
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
alert(data);
if (res.status === 200) {
navigate('/');
} else {
setId('');
setPw('');
return;
}
} catch(err) {
console.log(err);
}
}
}
return (
<div>
<h1>회원가입</h1>
<div>
<input type="text" value={id} onChange={(e) => setId(e.target.value)}/>
<input type="password" value={pw} onChange={(e) => setPw(e.target.value)}/>
<button type='submit' onClick={submitBtn}>가입</button>
</div>
</div>
);
};
export default Signup;
// user.js
const bcrypt = require('bcrypt');
const userDB = require('../models/userDB');
const textToHash = async (text) => { // 텍스트 값을 hash로 변환
const saltRounds = 10;
try {
const hash = await bcrypt.hash(text, saltRounds);
return hash
} catch (err) {
console.error(err);
return err;
}
}
exports.signup = async (req, res) => {
const { userID, userPW } = req.body;
try {
const getUser = await userDB.getUser(userID);
if (getUser.length) {
res.status(401).json('이미 존재하는 아이디입니다.');
return;
}
const hash = await textToHash(userPW);
const signUp = await userDB.signUp([userID, hash]);
res.status(200).json('가입 성공');
} catch (err) {
console.error(err);
res.status(500).json(err);
}
};
// userDB.js
const db = require('../database/db'); // 데이터베이스 연결 설정
exports.signUp = (data) => {
return new Promise((resolve, reject) => {
db.query(`INSERT INTO user (userID, userPW) VALUES (?, ?) `, [data[0], data[1]], (err, result) => {
if (err) reject(err);
else resolve(result);
});
});
};
// Login.jsx
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
const Login = () => {
const [id, setId] = useState('');
const [pw, setPw] = useState('');
const navigate = useNavigate();
const loginSubmit = async () => {
if (id === '' || pw === '') {
alert('아이디 또는 비밀번호를 입력해주시기 바랍니다');
return
} else {
try {
const res = await fetch('/api/loginCheck', {
method: 'POST',
body: JSON.stringify({userID: id, userPW: pw}),
credentials: 'include',
headers: {
'Content-Type': 'application/json'
},
});
const data = await res.json();
alert(data);
if (res.status === 200) {
navigate('/main');
} else {
setId('');
setPw('');
return;
}
} catch(err) {
console.log(err);
}
}
}
const moveSignUP = () => {
navigate('/signup');
}
return (
<>
<h1>로그인</h1>
<div>
<input type="text" value={id} onChange={(e) => setId(e.target.value)} required/>
<input type="password" value={pw} onChange={(e) => setPw(e.target.value)} required/>
<button type='submit' onClick={loginSubmit}>로그인</button>
</div>
<button onClick={moveSignUP}>회원가입</button>
</>
);
};
export default Login;
// user.js
const bcrypt = require('bcrypt');
const userDB = require('../models/userDB');
const hashCompare = async (inputValue, hash) => {
try {
const isMatch = await bcrypt.compare(inputValue, hash);
if (isMatch) return true;
else return false;
} catch(err) {
console.error(err);
return err;
}
}
exports.loginCheck = async (req, res) => {
const { userID, userPW } = req.body;
try {
const getUser = await userDB.getUser(userID);
if (!getUser.length) {
res.status(401).json('존재하지 않는 아이디입니다.');
return;
}
const blobToStr = Buffer.from(getUser[0].userPW).toString();
const isMatch = await hashCompare(userPW, blobToStr);
if (!isMatch) {
res.status(401).json('비밀번호가 일치하지 않습니다.');
return;
}
res.status(200).json('로그인 성공');
} catch (err) {
console.error(err);
res.status(500).json(err);
}
}
// userDB.js
const db = require('../database/db'); // 데이터베이스 연결 설정
exports.getUser = (userID) => {
return new Promise((resolve, reject) => {
db.query(`SELECT * FROM user where userID = ?`, userID, (err, result) => {
if (err) reject(err);
else resolve(result);
});
});
};
Main.jsx 파일 코드가 없는거 아닌가요?