이번 포스팅에서는 Node.js/Express 백엔드 프로젝트에 MySQL 데이터베이스를 연동하고, AWS RDS를 통해 데이터베이스를 설정하는 방법을 소개합니다. 또한 JWT 인증을 구현하여 사용자 인증까지 완료하는 전체 과정을 설명합니다.
1. 백엔드 기본 설정
프로젝트 폴더를 생성하고 기본적인 패키지들을 설치해줍니다.
sudo apt update
sudo apt upgrade
cd blahblah/backend
npm init -y
npm install express bcrypt jsonwebtoken dotenv cors mysql2
sudo apt install mysql-client-core-8.0
- express: 백엔드 프레임워크.
- bcrypt: 비밀번호 암호화.
- jsonwebtoken: JWT 토큰을 사용한 인증.
- dotenv: 환경 변수를 관리하기 위한 패키지.
- cors: CORS 설정을 도와주는 미들웨어.
- mysql2: MySQL과의 연결을 위한 패키지.
2. AWS RDS 설정
2-1. RDS에서 MySQL 인스턴스 생성
- AWS 콘솔에서 RDS로 이동한 후 "데이터베이스 생성"을 클릭합니다.
- MySQL을 선택하고, "프리 티어"나 적절한 요금제를 선택합니다.
- 인스턴스의 이름, 관리자 사용자 이름, 비밀번호를 설정합니다.
- 스토리지, 네트워크 설정에서 퍼블릭 액세스 허용을 체크합니다.
- 인스턴스 생성이 완료되면 **엔드포인트(DB 인스턴스의 호스트 주소)**를 확인합니다.
2-2. RDS 보안 그룹 설정
- RDS 보안 그룹에서 인바운드 규칙을 수정하여 로컬에서 MySQL에 접근할 수 있도록 설정합니다.
- 프로토콜: MySQL/Aurora (TCP, 포트 3306)
- 소스: 로컬 IP (혹은 0.0.0.0/0, 보안상 위험함)
- AWS 콘솔에서 RDS 인스턴스를 클릭하여 "수정" 버튼을 클릭 , 퍼블릭 액세스 설정을 "예"로 변경
( 퍼블릭 액세스는 외부에서 접근 가능하므로, 보안에 신경. 특히 포트 3306을 열어두면 외부에서 악의적인 접근 시도가 있을 수 있으니, 접근을 제어하기 위해 IP 주소를 제한하거나 VPN을 사용 등 보안 신경) - 보안그룹 인바운드 0.0.0.0/0 으로 하고 포트범위 3306로 설정해야함
2-3. MySQL 클라이언트로 연결 테스트
MySQL 클라이언트를 사용하여 RDS에 연결할 수 있는지 확인합니다.
mysql -h <RDS 엔드포인트> -P 3306 -u <사용자 이름> -p
mysql -h blahblah -P 3306 -u admin -p
(예시)
비밀번호를 입력하면 MySQL 콘솔에 접속할 수 있으며, 필요한 데이터베이스와 테이블을 생성합니다.
CREATE DATABASE blahblah;
3. 환경 변수 설정
데이터베이스 URI와 민감한 정보를 관리하기 위해 .env 파일을 생성하고 설정해줍니다.
touch .env
env 파일 내용:
DB_HOST=<RDS 엔드포인트>
DB_USER=<RDS 사용자 이름>
DB_PASSWORD=<RDS 비밀번호>
DB_NAME=blahblah
PORT=5000(서버가 실행되는 포트. MySQL의 포트를 의미하는 것이 아님. (MySQL의 기본 포트는 3306)
JWT_SECRET=yourGeneratedSecretKey
JWT_SECRET은 랜덤하게 생성된 비밀 키를 입력.
4. MySQL 연결 설정
MySQL과 연결할 수 있도록 설정 파일을 작성합니다.
package.json의 내용을 다음과 같이 바꿉니다.
("type" :"module", 부분 추가 > 웹페이지를 만들고 백엔드를 관리할 때 보통은 CommonJS(require, module.exports) 방식을 사용하지만, 최근 트렌드는 ES 모듈(import, export) 방식으로 이동)
{
"name": "backend",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.1.1",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.21.0",
"jsonwebtoken": "^9.0.2",
"jwks-rsa": "^3.1.0",
"mysql2": "^3.11.3"
}
}
4-1. MySQL 연결 설정 (db.js)
mkdir src
mkdir src/config
touch src/config/db.js
touch src/config/db.js
src/config/db.js 파일에 MySQL 연결 코드를 작성합니다:
import mysql from 'mysql2/promise';
import dotenv from 'dotenv';
dotenv.config();
const pool = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0,
});
// MySQL 연결 테스트
const testConnection = async () => {
try {
const connection = await pool.getConnection();
console.log('MySQL Database connected successfully');
connection.release(); // 연결 해제
} catch (error) {
console.error('Database connection failed:', error);
}
};
testConnection(); // 서버 시작 시 연결 테스트
export default pool;
이 코드는 MySQL에 대한 연결 풀을 생성하고, 서버 시작 시 연결 테스트를 실행합니다.
5. Express 서버 설정
5-1. Express 서버 기본 설정
mkdir src
touch src/app.js
src/app.js 파일에 Express 서버 및 MySQL 연결 테스트 코드를 작성합니다:
import express from 'express';
import pool from './config/db.js'; // MySQL 연결
import dotenv from 'dotenv';
import cors from 'cors';
dotenv.config();
const app = express();
const PORT = process.env.PORT || 5000;
app.use(cors({
origin: 'http://localhost:3000', // 필요한 프론트엔드 URL 추후에 연결 후 설정
credentials: true
}));
app.use(express.json());
// MySQL 연결 테스트 API
app.get('/', (req, res) => {
res.send('Welcome to the API!');
});
app.get('/api/test', async (req, res) => {
const [rows] = await pool.query('SELECT 1 + 1 AS solution');
res.json({ solution: rows[0].solution });
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
이 코드를 통해 /api/test 경로로 GET 요청을 보내면 MySQL 연결을 테스트할 수 있습니다.
6. 사용자 인증 및 JWT 발급
6-1. 사용자 모델 생성 (userModel.js)
mkdir src/models
touch src/models/userModel.js
src/models/userModel.js 파일에 MySQL을 사용하여 사용자 데이터를 처리하는 로직을 추가합니다.
import pool from '../config/db.js';
// 사용자 등록
export const registerUser = async (username, email, passwordHash) => {
const [result] = await pool.query(
'INSERT INTO users (username, email, password) VALUES (?, ?, ?)',
[username, email, passwordHash]
);
return result.insertId;
};
// 이메일로 사용자 찾기
export const findUserByEmail = async (email) => {
const [rows] = await pool.query('SELECT * FROM users WHERE email = ?', [email]);
return rows[0];
};
6- 2. 사용자 컨트롤러 작성 (userController.js)
mkdir src/controllers
touch src/controllers/userController.js
src/controllers/userController.js 파일에 회원가입과 로그인 로직을 작성합니다.
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import { registerUser, findUserByEmail } from '../models/userModel.js';
// 회원가입 처리
export const register = async (req, res) => {
const { username, email, password } = req.body;
const passwordHash = await bcrypt.hash(password, 10);
try {
const userId = await registerUser(username, email, passwordHash);
res.status(201).json({ message: 'User registered successfully', userId });
} catch (error) {
res.status(400).json({ message: 'Error registering user', error });
}
};
// 로그인 처리
export const login = async (req, res) => {
const { email, password } = req.body;
try {
const user = await findUserByEmail(email);
if (!user) return res.status(400).json({ message: 'User not found' });
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) return res.status(400).json({ message: 'Invalid credentials' });
// JWT 토큰 발급 (1시간 유효)
const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET, { expiresIn: '1h' });
res.json({ token });
} catch (error) {
res.status(400).json({ message: 'Error logging in', error });
}
};
6-3. 사용자 라우트 설정 (userRoutes.js)
mkdir src/routes
touch src/routes/userRoutes.js
src/routes/userRoutes.js 파일에서 사용자 등록 및 로그인 API를 정의합니다.
import express from 'express';
import { register, login } from '../controllers/userController.js';
const router = express.Router();
router.post('/register', register);
router.post('/login', login);
export default router;
6-4. Express 서버에 라우트 연결(app.js)
import userRoutes from './routes/userRoutes.js';
app.use('/api/users', userRoutes); // 사용자 라우트 연결
7. JWT 검증 미들웨어
JWT 토큰을 검증하기 위한 미들웨어를 작성합니다.
mkdir src/middleware
touch src/middleware/authMiddleware.js
src/middleware/authMiddleware.js:
import jwt from 'jsonwebtoken';
export const verifyToken = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1]; // Bearer 토큰 추출
if (!token) {
return res.status(401).json({ message: 'No token provided' });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET); // 토큰 검증
req.user = decoded; // 검증된 정보 저장
next(); // 다음 미들웨어로 이동
} catch (error) {
res.status(401).json({ message: 'Invalid token' });
}
};
JWT 검증 미들웨어를 API 경로에 적용하여 인증된 사용자만 접근할 수 있도록 설정합니다.
import { verifyToken } from './middleware/authMiddleware.js';
// 보호된 경로에 JWT 검증 미들웨어 적용
app.get('/protected', verifyToken, (req, res) => {
res.json({ message: 'You are authorized', user: req.user });
});
8. 서버 실행
최종 코드
import express from 'express';
import pool from './config/db.js'; // MySQL 연결
import dotenv from 'dotenv';
import cors from 'cors';
import userRoutes from './routes/userRoutes.js';
import jwt from 'jsonwebtoken';
// 환경 변수 설정
dotenv.config();
// Express 앱 생성
const app = express();
const PORT = process.env.PORT || 5000;
// 미들웨어 설정
app.use(cors({
origin: 'http://localhost', // 필요한 프론트엔드 URL 설정
credentials: true
}));
app.use(express.json());
// JWT 검증 미들웨어 함수
export const verifyToken = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1]; // Bearer 토큰 추출
if (!token) {
return res.status(401).json({ message: 'No token provided' });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET); // 토큰 검증
req.user = decoded; // 검증된 정보 저장
next(); // 다음 미들웨어로 이동
} catch (error) {
res.status(401).json({ message: 'Invalid token' });
}
};
// 사용자 라우트 연결
app.use('/api/users', userRoutes);
// 기본 라우트 설정
app.get('/', (req, res) => {
res.send('Welcome to the API!');
});
// MySQL 연결 테스트 API
app.get('/api/test', async (req, res) => {
try {
const [rows] = await pool.query('SELECT 1 + 1 AS solution');
res.json({ solution: rows[0].solution });
} catch (error) {
console.error('MySQL 연결 실패:', error);
res.status(500).json({ error: 'MySQL 연결 실패' });
}
});
// 서버 시작
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
모든 설정이 완료되었으니 서버를 실행하여 MySQL RDS와의 연결을 확인합니다.
node src/app.js
서버가 정상적으로 실행되면, JWT 인증과 MySQL 데이터베이스 연동이 완료됩니다.
결론
이제 Node.js/Express와 MySQL, AWS RDS를 연동한 백엔드가 완성되었습니다. JWT 토큰을 사용한 인증 기능을 통해 사용자를 보호할 수 있으며, AWS RDS를 사용해 데이터베이스를 확장성 있게 운영할 수 있습니다.
이 과정을 통해 여러분의 애플리케이션에 안정적이고 확장 가능한 백엔드를 구성할 수 있습니다.
'개인서버' 카테고리의 다른 글
AWS 배포 방법 정리 (1) | 2024.09.26 |
---|---|
AWS S3와 EC2 설명 및 S3연결 방법 (0) | 2024.09.25 |
프로젝트 구조 정리 (2) | 2024.09.24 |
전체 웹사이트 구축 프로세스 정리 (0) | 2024.09.19 |