JavaScript/Node JS
Java Script(16)-MySQL DBMS node.js연동
두설날
2024. 5. 8. 10:52
*이 글을 읽기전에 작성자 개인의견이 있으니, 다른 블로그와 교차로 읽는것을 권장합니다.*
ORM(객체 관계 매핑, Object Relational Mapping)
- 객체 지향 프로그래밍 언어에서 사용되는 객체와 관계형 데이터베이스 간의 불일치를 해결하기 위한 기술
- 객체 모델과 관계형 데이터베이스의 테이블 간의 매핑을 수행하여 개발자가 SQL 쿼리 대신 객체 지향 코드를 사용할 수 있도록 함
ODM(객체 문서 매핑, Object Document Mapping)
- NoSQL 데이터베이스와 객체 지향 프로그래밍 언어 간의 매핑을 제공하는 기술
- 주로 문서 지향 데이터베이스(MongoDB)와 함께 사용
현재 작업중인 브랜치를 확인
- 목록을 확인
git branch
- * 표시가 되어 있는 것이 현재 작업중인 브랜치
branch 생성하기
git branch 브랜치이름
branch 전환하기
git switch 브랜치이름
git checkout 브랜치이름
branch 생성과 동시에 전환하기
git checkout -b 브랜치이름
use kdt;
create table users (
id int auto_increment primary key,
username varchar(50) unique not null,
password varchar(150) not null,
name varchar(50) not null,
email varchar(50) not null,
url varchar(200)
);
drop table tweets;
create table tweets (
id int auto_increment primary key,
userId int,
createdAt datetime default now(),
text varchar(2000) not null,
foreign key(userId) references users(id)
);
select * from users;
select * from tweets;
// package.json 파일
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "app.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon app"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"nodemon": "^3.1.0"
},
"dependencies": {
"bcrypt": "^5.1.1",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express-validator": "^7.0.1",
"jsonwebtoken": "^9.0.2",
"morgan": "^1.10.0",
"mysql2": "^3.9.7",
"socket.io": "^4.7.5"
}
}
// app.js파일
import express from "express";
import morgan from "morgan";
import tweetsRouter from './router/tweets.js';
import authRouter from './router/auth.js';
import { config } from "./config.js";
import { db } from './db/database.js';
const app = express();
app.use(express.json());
app.use(morgan("dev"));
app.use('/tweets', tweetsRouter);
app.use('/auth', authRouter);
app.use((req, res, next) => {
res.sendStatus(404);
});
// DB 연결 테스트!
// db.getConnection().then(connection => console.log(connection));
app.listen(config.host.port
// config.js 파일
import dotenv from 'dotenv';
dotenv.config();
function required(key, defaultValue=undefined){
const value = process.env[key] || defaultValue; // or: 앞의 값이 true로 판별되면 앞의 값이 대입되고 값이 false로 판별되면 뒤에 값이 대입됨
if(value == null){
throw new Error(`키 ${key}는 undefined!!`);
}
return value;
}
export const config = {
jwt: {
secretKey: required('JWT_SECRET'),
expiresInSec: parseInt(required('JWT_EXPIRES_SEC', 172800))
},
bcrypt: {
saltRounds: parseInt(required('BCRYPT_SALT_ROUNDS', 10))
},
host: {
port: parseInt(required('HOST_PORT', 8080))
},
db: {
host: required('DB_HOST'),
user: required('DB_USER'),
database: required('DB_DATABASE'),
password: required('DB_PASSWORD'),
port: required('DB_PORT')
}
}
// controller > auth.js 파일
import * as authRepository from '../data/auth.js';
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import { config } from '../config.js';
function createJwtToken(id){
return jwt.sign({id}, config.jwt.secretKey, {expiresIn: config.jwt.expiresInSec});
}
export async function signup(req, res, next){
const {username, password, name, email, url} = req.body;
const found = await authRepository.findByUsername(username);
if(found){
return res.status(409).json({message:`${username}이 이미 있습니다`});
}
const hashed = await bcrypt.hash(password, config.bcrypt.saltRounds);
const userId = await authRepository.createUser({username, hashed, name, email, url});
const token = createJwtToken(userId);
res.status(201).json({token, username});
}
export async function login(req, res, next){
const {username, password} = req.body;
// const user = await authRepository.login(username);
const user = await authRepository.findByUsername(username);
console.log(user);
if(!user){
return res.status(401).json({message: `아이디를 찾을 수 없음`});
}
const isValidpassword = await bcrypt.compareSync(password, user.password);
if(!isValidpassword){
return res.status(401).json({message: `비밀번호가 틀렸음`});
}
const token = createJwtToken(user.id);
res.status(200).json({token, username});
}
// export async function verify(req, res, next){
// const token = req.header['Token'];
// if(token){
// res.status(200).json(token);
// }
// }
export async function me(req, res, next){
const user = await authRepository.findById(req.userId);
console.log(user);
if(!user){
return res.status(404).json({message: `일치하는 사용자가 없음`});
}
res.status(200).json({token: req.token, username: user.username});
}
// controller > tweet.js 파일
import * as tweetRepository from '../data/tweet.js';
// 여러 트윗을 가져오는 함수
export async function getTweets(req, res){
const username = req.query.username;
const data = await (username ? tweetRepository.getAllByUsername(username)
: tweetRepository.getAll());
res.status(200).json(data);
}
// 하나의 트윗을 가져오는 함수
export async function getTweet(req, res, next) {
const id = req.params.id;
const tweet = await tweetRepository.getById(id);
if(tweet){
res.status(200).json(tweet);
}else{
res.status(404).json({message: `${id}의 트윗이 없습니다`})
}
}
// 트윗을 생성하는 함수
export async function createTweet(req, res, next) {
const { text } = req.body;
const tweet = await tweetRepository.create(text, req.userId);
res.status(201).json(tweet);
}
// 트윗을 변경하는 함수
export async function updateTweet(req, res, next) {
const id = req.params.id;
const text = req.body.text;
const tweet = await tweetRepository.update(id, text);
if(tweet){
res.status(201).json(tweet);
}else{
res.status(404).json({message: `${id}의 트윗이 없습니다`})
}
}
// 트윗을 삭제하는 함수
export async function deleteTweet(req, res, next) {
const id = req.params.id;
await tweetRepository.remove(id);
res.sendStatus(204);
}
// data > auth.js 파일
import { db } from '../db/database.js';
// 아이디(username) 중복검사
export async function findByUsername(username){
return db.execute('select * from users where username = ?', [username]).then((result) => {
console.log(result);
return result[0][0];
});
}
// id 중복검사
export async function findById(id){
return db.execute('select * from users where id = ?', [id]).then((result) => {
console.log(result);
return result[0][0];
});
}
export async function createUser(user){
console.log(user);
const {username, hashed, name, email, url} = user;
return db.execute('insert into users (username, password, name, email, url) values (?, ?, ?, ?, ?)', [username, hashed, name, email, url]).then((result) => {
console.log(result); // result[0].insertId
return result[0].insertId;
});
}
// export async function login(username){
// const user = users.find((user) => user.username === username)
// return user;
// }
// data > tweet.js 파일
import { db } from '../db/database.js';
const SELECT_JOIN = 'select tw.id, tw.text, tw.createdAt, tw.userId, us.username, us.name, us.email, us.url from tweets as tw join users as us on tw.userId = us.id';
const ORDER_DESC = 'order by tw.createdAt desc';
// 모든 트윗을 리턴
export async function getAll() {
return db.execute(`${SELECT_JOIN} ${ORDER_DESC}`).then((result) => {
console.log(result);
return result;
});
}
// 해당 아이디에 대한 트윗을 리턴
export async function getAllByUsername(username){
return db.execute(`${SELECT_JOIN} where username = ? ${ORDER_DESC}`, [username]).then((result) => {
console.log(result);
return result;
});
}
// 글번호에 대한 트윗을 리턴
export async function getById(id){
return db.execute(`${SELECT_JOIN} where tw.id = ? ${ORDER_DESC}`, [id]).then((result) => {
console.log(result);
return result;
});
}
// 트윗을 작성
export async function create(text, userId){
return db.execute('insert into tweets (text, userId) values (?, ?)', [text, userId]).then((result) => {
console.log(result);
return getById(result[0].insertId);
});
}
// 트윗을 변경
export async function update(id, text){
return db.execute('update tweets set text = ? where id = ?', [text, id]).then((result) => {
console.log(result);
return getById(id);
});
}
// 트윗을 삭제
export async function remove(id){
return db.execute('delete from tweets where id = ?', [id]);
}
// db > database.js 파일
import mysql from 'mysql2';
import { config } from '../config.js';
const pool = mysql.createPool({
host: config.db.host,
port: config.db.port,
user: config.db.user,
database: config.db.database,
password: config.db.password
});
export const db = pool.promise();