카테고리 없음

Express && MySQL 예제

swchung09 2025. 8. 2. 21:01

이번에는 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군데를 설명해보았다.