IT속으로

Node.js + MySQL + bcrypt로 회원가입 & 로그인 만들기

더월드 2025. 4. 6.

보안은 기본! 회원가입 시 비밀번호 암호화까지 완벽하게!

  • express, express-session, body-parser
  • mysql2: MySQL 클라이언트
  • bcrypt: 비밀번호 암호화

1. 패키지 설치

npm install express express-session body-parser mysql2 bcrypt

 

2. MySQL 테이블 구조 (비밀번호 저장 길이)

CREATE DATABASE test;

USE test;

CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(50) UNIQUE NOT NULL,
  password VARCHAR(255) NOT NULL
);

 

3. 전체 코드 (index.js)

  • /register에서 회원가입 (아이디 중복 체크 & 암호화 저장)
  • /login에서 로그인 시도
  • 비밀번호 비교 후 세션 저장
  • /mypage에서 로그인된 사용자만 접근 가능
  • /logout으로 세션 제거
const express = require('express');
const bodyParser = require('body-parser');
const session = require('express-session');
const mysql = require('mysql2');
const bcrypt = require('bcrypt');

const app = express();
const PORT = 3000;

// MySQL 연결 설정
const db = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: '',  // 비밀번호 입력
  database: 'test'
});

db.connect(err => {
  if (err) throw err;
  console.log('MySQL 연결 완료');
});

// 미들웨어
app.use(bodyParser.urlencoded({ extended: true }));
app.use(session({
  secret: 'bcryptSecretKey',
  resave: false,
  saveUninitialized: true
}));

// 회원가입 페이지
app.get('/register', (req, res) => {
  res.send(`
    <h2>회원가입</h2>
    <form method="post" action="/register">
      <input type="text" name="username" placeholder="아이디" required />
      <input type="password" name="password" placeholder="비밀번호" required />
      <button type="submit">가입하기</button>
    </form>
    <p><a href="/login">로그인 페이지로</a></p>
  `);
});

// 회원가입 처리
app.post('/register', async (req, res) => {
  const { username, password } = req.body;

  const hashedPw = await bcrypt.hash(password, 10); // 비밀번호 암호화

  const sql = 'INSERT INTO users (username, password) VALUES (?, ?)';
  db.query(sql, [username, hashedPw], (err) => {
    if (err) {
      if (err.code === 'ER_DUP_ENTRY') {
        return res.send('이미 존재하는 아이디입니다.');
      }
      return res.send('회원가입 실패');
    }

    res.send('<h3>회원가입 성공! <a href="/login">로그인</a></h3>');
  });
});

// 로그인 폼
app.get('/login', (req, res) => {
  if (req.session.user) return res.redirect('/mypage');

  res.send(`
    <h2>로그인</h2>
    <form method="post" action="/login">
      <input type="text" name="username" placeholder="아이디" required />
      <input type="password" name="password" placeholder="비밀번호" required />
      <button type="submit">로그인</button>
    </form>
    <p><a href="/register">회원가입</a></p>
  `);
});

// 로그인 처리
app.post('/login', (req, res) => {
  const { username, password } = req.body;

  const sql = 'SELECT * FROM users WHERE username = ?';
  db.query(sql, [username], async (err, results) => {
    if (err) return res.send('DB 오류');

    if (results.length === 0) {
      return res.send('<h3>사용자 없음</h3>');
    }

    const user = results[0];
    const isMatch = await bcrypt.compare(password, user.password);

    if (isMatch) {
      req.session.user = { id: user.id, username: user.username };
      res.redirect('/mypage');
    } else {
      res.send('<h3>비밀번호가 틀렸습니다.</h3>');
    }
  });
});

// 마이페이지
app.get('/mypage', (req, res) => {
  if (!req.session.user) return res.redirect('/login');

  res.send(`
    <h2>마이페이지</h2>
    <p>${req.session.user.username}님, 환영합니다</p>
    <a href="/logout">로그아웃</a>
  `);
});

// 로그아웃
app.get('/logout', (req, res) => {
  req.session.destroy(() => {
    res.redirect('/login');
  });
});

// 서버 시작
app.listen(PORT, () => {
  console.log(`서버 실행 중: http://localhost:${PORT}`);
});

 

암호화 방식 설명

  • bcrypt.hash(password, saltRounds)
    → 비밀번호를 해시해서 저장 (한 방향 암호화)
  • bcrypt.compare(입력값, 저장된 해시)
    → 로그인 시 비교 가능 (일치 여부만 판단)

비밀번호는 DB에 절대 평문으로 저장하면 안 됩니다!
bcrypt는 안전한 암호화 알고리즘 중 하나입니다. 

 

코드 실행

  • cmd창에서 node index.js
  • 브라우저에서 "localhost:3000/register" 페이지 접속
  • 'user1', '1234'으로 계정 생성
  • mysql db 정상적으로 비밀번호가 암호화 되었는지 확인.

댓글

💲 추천 글