이번에는 Express와 MySQL을 연동하여 구축해본 테스트 서버를 설명하고, 만들면서 발생한 문제를 해결하는 과정을 적었다.
우선 node로 직접 실행할 app.js를 생성한다.
const express = require('express'); // Express 프레임워크 불러오기
const session = require('express-session'); // Express 프레임워크에서 사용할 세션 불러오기
const db = require('./db'); // db.js에서 db 불러오기(추후 설명)
const loginRouter = require('./routes/login') // login.js에서 로그인 라우터 불러오기(추후 설명)
const registerRouter = require('./routes/register') // register.js에서 회원가입 라우터 불러오기(추후 설명)
const app = express(); // app 객체 생성
const port = 3000; // 앱에서 사용할 포트
app.set('view engine', 'pug'); // pug 템플릿 엔진 사용
app.set('views', './views');
app.use(session({ // 세션 사용
secret: 'secret-key', // 세션에서 사용할 비밀번호
resave: false, // 요청마다 세션을 다시 쓰지 않음
saveUninitialized: true // 세션이 비어있어도 사용
});
app.use('/login', loginRouter); // 로그인 라우터 사용
app.use('/register', registerRouter); // 회원가입 라우터 사용
app.get('/', (req, res) => { // 메인 페이지
res.render('index', {username: req.session.username});
});
app.listen(port, (err) => { // 서버 실행
if (err) {
console.log(`에러: ${err}`);
}else {
console.log(`서버가 http://localhost:${port} 에서 실행 중입니다.`);
}
}
다음으로 db.js로 MySQL DB를 불러온다.
const mysql = require('mysql2'); // MySQL 불러오기
const dotenv = require('dotenv'); // .env에서 환경 변수 불러오는 용도
dotenv.config(); // .env에서 환경 변수를 불러오기
const db = mysql.createConnection({ // DB 불러오기
host: process.env.DB_HOST, // DB 주소(대부분의 경우 127.0.0.1(localhost))
user: process.env.DB_USER, // DB 사용자 이름(대부분의 경우 root나 user)
password: process.env.DB_PASSWORD, // DB 비밀번호
database: process.env.DB_NAME // DB 이름
});
db.connect((err) => { // DB 연결
if (err) {
console.error(`DB 연결 에러: ${err}`);
}else {
console.log('DB에 연결되었습니다.');
}
});
module.exports = db; // 중요!
여기서 난 module.exports를 설정하지 않아서, 다른 곳에서 require로 불러오지 못하는 버그가 있었다. 꼭 적어주도록 하자.
이제 db.js로 DB를 불러올 수 있게 되었다. 다음으로는 /routes에 login.js로 로그인 기능을 구현해보자.
const express = require('express'); // Express 프레임워크 불러오기
const db = require('../db'); // 상위 폴더에 있는 db.js 불러오기
const router = express.Router(); // 라우터 객체 생성
router.use(express.json()); // 모든 요청을 json 객체로 파싱
router.use(express.urlencoded({extended: false}); // application/x-www-form-urlencoded를 파싱하는 설정
router.get('/', (req, res) => { // /login get 처리
const message = req.session.message; // 1회용 메시지 베너
req.session.message = null;
res.render('login', {message: message});
});
router.post('/', (req, res) => { // /login post(폼 제출) 처리
const {username, password} = req.body; // 중요!
// DB에서 값 찾아보기
db.query('SELECT * FROM info WHERE username = ? AND password = ?', [username, password], (err, results, fields) => {
if (results.length > 0) {
req.session.isLoggedIn = true;
req.session.username = results[0].username;
req.session.message = '로그인 성공'; // 로그인 성공 배너 메시지
res.redirect('/'); // /로 이동
}else {
req.session.message = '로그인 실패'; // 로그인 실패 배너 메시지
res.redirect('/login'); // /login으로 이동
}
});
});
module.exports = router; // app.js에서 불러오기 위한 설정
여기서 난 const {username, password} = req.body;로 하지 않고 []로 받아서 에러가 발생하였다. 이는 req.body가 배열이 아니라 키와 값이 매칭되는 객체 형태이기 때문에 {}로 파싱해야한다.
이제 회원 가입을 위해 /routes에 register.js를 만들어보자.
const express = require('express'); // Express 프레임워크 불러오기
const db = require('db'); // DB 불러오기
const router = express.Router(); // 라우터 객체 생성
router.use(express.json()); // 모든 요청을 json으로 파싱
router.use(express.urlencoded({extended: false})); // application/x-www-form-urlencoded를 파싱하는 설정
router.get('/', (req, res) => { // /register get 처리
const message = req.session.message; // 1회용 베너 메시지
req.session.message = null;
res.render('register', {message: message});
});
rotuer.post('/', (req, res) => { // /register post(폼 제출) 처리
const {username, password} = req.body; // username과 password 파싱
// 이미 DB에 있는 아이디인지 확인
db.query('SELECT COUNT(*) FROM info WHERE username = ?', [username], (err, results, fields) => {
const count = results[0]['COUNT(*)'];
if (count === 0){
// DB에 값 추가
db.query('INSERT INTO info (username, password) VALUES (?, ?)', [username, password], (err, results) => {
if (err) {
console.error(`회원가입 에러: ${err}`);
}else {
req.session.message = '회원가입 성공'; // 회원 가입 성공 배너 메시지
}
});
}
});
});
module.exports = router; // app.js에서 불러오기 위한 설정
이후 index.pug, login.pug, register.pug는 다음과 같이 작성하면 된다.
index.pug
doctype html
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title 메인 페이지
body
if username
h1 Welcome #{username} !!
else
h1 Login first
a(href="/login") Login
login.pug
doctype html
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title 로그인
body
if message
p #{message}
h2 로그인
form(action="/login", method="post")
label(for="username") 사용자 이름 :
input(type="text", id="username", name="username", required)
br
label(for="password") 비밀번호 :
input(type="text", id="password", name="password", required)
br
button(type="submit") 로그인
register.pug
doctype html
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title 회원가입
body
if message
p #{message}
h2 회원가입
form(action="/register", method="post")
label(for="username") 사용자 이름 :
input(type="text", id="username", name="username", required)
br
label(for="password") 비밀번호 :
input(type="text", id="password", name="password", required)
br
button(type="submit") 회원가입
이렇게 Express - MySQL을 연동시킨 예제의 코드를 분석하고, 내가 실수한 2군데를 설명해보았다.