MVC 패턴 구조와 함께 회원가입, 로그인, 회원정보 수정, 회원 탈퇴를 DB와 연동하여 구현하는 예제를 풀어보자. 이때, CRUD도 이용해보자.
📌 npm 세팅
npm init -y
npm i express ejs dotenv cross-env mysql2
만약, nodemon 설치를 이전에 한적이 없다면 이것도 하자!
nodemon
: 파일들을 모니터링 하다가 소스코드 변경시 자동으로 node 재실행 하는 패키지
npm i -g nodemon //전역 설치라 한번 설치하면 새로운 파일 생성할때마다 설치안해도 된다.
nodemon -v
우선, app.js를 만들면서 어떤식으로 만들지 틀을 정했다.
require('dotenv').config(); //환경변수를 위한 모듈
const express = require(express);
const app = express();
const PORT = 8000;
//미들웨어
app.set('view engine', 'ejs');
app.use(express.json());
//router
const indexRouter = require('./routes/Rindex'); //page여는 역할의 페이지
app.use('/', indexRouter);
const userRouter = require('./routes/Ruser'); //CRUD를 포함하고 있는 페이지들의 첫 url
app.use('/api/user', userRouter);
//오류처리
app.get('*', (req, res) => {
res.status(404).render('404');
});
//서버연결
app.listen(PORT, () => {
console.log(`http://localhost:${PORT}`);
});
➡️ 초반세팅(미들웨어, 오류처리, 서버연결)은 거의 늘 비슷하고, router만 변경했다.
➡️ indexRouter
: 홈페이지를 여는 역할
➡️ userRouter
: 클라이언트의 요청 중 /api/user로 시작하는 모든 경우를 처리하고, 사용자 관련 CRUD
(Create, Read, Update, Delete) 작업을 수행한다.
📌 Controller
: 사용자의 입력을 받아 처리하고, 적절한 Model을 호출하여 데이터를 처리하도록 요청한다. 그리고 Model에서 받은 결과를 View에 전달하여 사용자에게 보여주도록 하는 역할을 한다.
//main 함수 index.ejs 뷰를 렌더링하여 응답을 보내는 역할
exports.main = (req, res) => {
res.render('index');
};
// 로그인 페이지를 보여주는 역할
exports.login = (req, res) => {
res.render('login');
};
//회원가입하는 페이지를 보여주는 역할
exports.signUp = (req, res) => {
res.render('signUp');
};
// 고객 정보 조회(사용자 프로필) 페이지를 보여주는 역할
exports.profile = (req, res) => {
res.render('profile');
};
➡️ res.render(viewName)
: 이 함수는 viewName에 해당하는 뷰를 렌더링하고, 이때 사용되는 템플릿 엔진(예: EJS, Pug 등)에 따라 해당 뷰에 데이터를 삽입하여 HTML을 생성하고 클라이언트에게 보낸다.
controller.signUp
함수는 'signUp' 뷰를 렌더링하여 응답을 보낸다.const express = require('express');
const controller = require('../controller/Cindex');
const router = express.Router();
//localhost:8000/
router.get('/', controller.main);
router.get('/login', controller.login);
router.get('/signUp', controller.signUp);
//각 고객마다 고유의 id를 통해 해당하는 고객 정보를 띄어줘야 하므로 /:id로 생성
router.get('/profile/:id', controller.profile);
//하나의 router만 있더라도 module로 꼭 외부로 내보내야한다.
module.exports = router;
const express = require('express');
const controller = require('../controller/Cuser');
const router = express.Router();
//app.js에서 언급했던 것 처럼, Ruser.js는 /localhost:8000/api/user로 시작하는 페이지를 가진다.
//POST /signUp 회원가입(비밀번호가 있으니까 get이 아니라 post방식으로 )
router.post('/signUp', controller.CsignUp);
//POST /login 로그인
router.post('/login', controller.Clogin);
//POST /info 회원정보
router.get('/info/:id', controller.Cinfo);
//PATCH /update 회원수정 , 수정할 땐 방식을 patch 사용
router.patch('/update', controller.Cupdate);
//DELETE /delete 정보삭제
router.delete('/delete', controller.Cdelete);
module.exports = router;
async/await
를 이용하였다.const User = require('../model/Muser');
//회원가입
exports.CsignUp = async (req, res) => {
console.log(res.body); //post방식이므로 res.body로 받아와서 잠시 저장.
const result = await User.MsignUp(req.body); //model의 Muser에서 쿼리문을 통해 받아온 rows
console.log('signUp', result);
res.json({ result: true });
};
//로그인
exports.Clogin = async (req, res) => {
console.log(req.body);
const result = await User.Mlogin(req.body);
console.log('login', result);
if (result.length >= 1) {
res.json({ result: true, message: '로그인 성공', data: result[0] }); //프론트에만 보여주는 결과
} else {
res.json({ result: false, message: '로그인 실패', id: null }); //프론트에게 이 값이 옳지 않다는 것을 정확하게 알려주기 위해 id를 null로 설정
}
};
//회원정보 조회
exports.Cinfo = async (req, res) => {
console.log(req.params.id);
const result = await User.Minfo(req.params.id);
console.log('info', result); // 처리가 완료될 때까지 기다린 후 그 결과를 'result'에 저장
if (result.length > 0) {
res.json({ result: true, info: result[0], message: '회원존재' });
} else {
res.json({ result: false, info: null, message: '존재하지 않는 회원' });
}
};
//회원정보 수정
exports.Cupdate = async (req, res) => {
const result = await User.Mupdate(req.body);
console.log('update', result);
res.json({ result: true });
};
//회원정보 삭제
exports.Cdelete = async (req, res) => {
const result = await User.Mdelete(req.body); //body에는 id하나만 받아오게 되는 것
console.log('delete', result);
res.json({ result: true });
};
➡️ 따로 모듈로 exports하지않고 함수 실행 즉시 export하였다.
➡️ controller
의 역할인 적절한 Model을 호출하여 데이터를 처리하도록 요청하고, Model에서 받은 결과를 View에 전달하여 사용자에게 보여주도록 하였다.(각 기능에 해당하는 함수를 작성)
model/Muser.js
와 프론트에 보이는 views
에 들어가는 여러 ejs파일(404.ejs,login.ejs 등), MySQL을 통한 DB생성은 다음 글에서 설명해보겠다.