Node에서 MySQL 연결
npm install mysql
로 설치
model에서 connection
import mysql from 'mysql';
const conn = mysql.createConnection({
host : 'localhost', //DB가 설치된 호스트 IP주소
user : 'user', //DB 접속 유저이름
password : '1234', // 비밀번호
database : 'kdt', //DB 이름
});
-> 외부에서 최상위 root 계정에서 접근을 허용하지 않아 새로운 계정을 만들고 접근해야 함.
MySQL 사용자 추가
//사용자 추가
CREATE USER 'user'@'%' IDENTIFIED BY '비밀번호';
//권한 부여
GRANT ALL PRIVILEGES ON *.* TO 'user'@'%' WITH GRANT OPTION;
//캐시 지우고 새로운 설정 적용
FLUSH PRIVILEGES;
//비밀번호 변경
ALTER USER 'user'@'%' IDENTIFIED WITH mysql_native_password BY '비밀번호';
model에서 데이터 접근 후 controller로 view에 데이터 전달
//model/Visitor.js
export const getVisitors =(cb)=> {
conn.query('SELECT * FROM visitor', (err, rows)=> {
if(err) {
throw err;
}
console.log(rows); //객체배열 형식으로 전달
cb(rows); //콜백
};
};
//controller/visitorController.js
export const getVisitors =(req, res)=> {
Visitor.getVisitors((result)=> {
res.render('visitor', {data : result}); //받은 테이터 view에 전달
});
};
Sequelize
자바스크립트 구분을 SQL로 변환, DB작업을 쉽게 할 수 있도록 도와주는 ORM 라이브러리 중 하나
ORM(Object Relation Mapping)
- 객체와 DB 테이블을 매핑시켜 관계형 데이터베이스를 객체지향적으로 사용하게 해주는 기술
ex) Node의 Sequelize, Java의 Mybatis, JPA/Hibernate
sequelize 설치
npm install sequelize sequelize-cli mysql2
sequelize - 시퀄라이즈 패키지
sequelize-cli - 시퀄라이즈 명령어 실행
mysql2 - mysql과 시퀄라이즈 연결하는 드라이버
npx sequelize init
- 시퀄라이즈 사용에 필요한 폴더 생성
Sequelize 모델 정의
import {DataTypes} from "sequelize";
const classesModel =(sequelize)=> {
const Classes = sequelize.define(
'Classes',
{
id : {
type : DataTypes.INTEGER,
allowNull : false,
autoIncrement : true,
primaryKey : true
},
name : {
type : DataTypes.STRING(30),
allowNull : false,
},
room : {
type : DataTypes.STRING(10),
allowNull : true,
},
code : {
type : DataTypes.STRING(10),
allowNull : false,
},
professor : {
type : DataTypes.STRING(15),
allowNull : true,
},
}
);
return Classes;
}
export default classesModel;
이외에 컬럼 정의 시 comment
, validate
속성 사용 가능
define()의 모델 옵션 정의(세번째 인자)
{
charset : 'utf8',
collate : 'utf8_general_ci'
tableName : 테이블 이름 설정
freezeTableName : true // 이름을 복수로 설정하지 않음
timestamps : true //createdAt, updatedAt
}
Sequelize 쿼리문
findAll()
,findOne()
- select
create()
- insert
update()
- update
destroy()
- delete
Seqeulize 쿼리문은 모두 Promise 반환하여.then()
메서드 붙여 결과처리 가능
config/config.json
json형식 파일을 이용해 Sequelize, MySQL 테이블 연결
config/config.json
{
'development' : {
"username": "user",
"password" : "1234",
"database": "kdt8",
"host": "127.0.0.1",
"dialect": "mysql"
}
},
...
models/index.js
const db = {};
import Sequelize from "sequelize";
import { readFile } from 'fs/promises';
const json = JSON.parse( await readFile(new URL('../config/config.json', import.meta.url)));
const devConfig = json.development;
const sequelize = new Sequelize(devConfig.database, devConfig.username, devConfig.password, devConfig);
//model
import Student from "./Student.js";
import Classes from './Classes.js';
import StudentProfile from "./StudentProfile.js";
db.Student = Student(sequelize);
db.Classes = Classes(sequelize);
db.StudentProfile = StudentProfile(sequelize);
db.sequelize = sequelize;
db.Sequelize = Sequelize;
export default db;
import jsonFile from '../config/config.json' assert { type : json};
로도 import할 순 있지만, 애플리케이션에서 해당 코드에 대해 warning으로 경고를준다. 번거롭더라도 fileSystem module을 이용해 파싱하는 방식으로 불러오는것이 안전할 것 같다.
Sequelize를 이용한 CRUD
import { default as User } from '../model/User.js';
import models from '../models/index.js';
import { Op } from 'sequelize';
const main = (req, res) => res.render('index');
const signUpGet = (req, res) => res.render('signup');
const signUpPost = (req, res) => {
models.User.create({ //models에서 정의한 테이블 컬럼명과 대소문자 일치해야함
userid : req.body.userId,
pw : req.body.userPwd,
name : req.body.userName,
}).then((result)=> {
console.log('result : ', result);
res.send({ result : true });
})
}
const signInGet = (req, res) => res.render('signin');
const signInPost = (req, res)=> {
models.User.findOne({
where : {
userid : req.body.userId,
pw : req.body.userPwd,
},
}).then((result)=> {
console.log('result : ', result);
res.render('profile', {'userInfo' : result}); // result.dataValues 생략 가능
});
}
const editInfo = (req, res) => {
const { userid, pw, name, id } = req.body;
models.User.update({
userid, pw, name //객체 구조분해할당 적용 가능, 변수명과 컬럼명 같으면 하나로 생략가능
}, {
where : {
id,
}
}).then((result)=> {
console.log(result); // result [1]
});
}
const deleteInfo = (req, res) => {
const { id } = req.body;
models.User.destroy({ where : { id } }).then((result)=> {
console.log('result : ', result); //result 1
res.send(true);
})
}
const findAll = (req, res) => {
models.User.findAll({
//attribute : 원하는 컬럼 조회
// attributes : ['name'],
//where : 조건
//Op.gt(초과), Op.gte(이상) Op.lt(미만), Op.ne(같지않은)
//Op.or(또는), Op.in(배열 요소 중 하나), Op.notIn(배열 요소와 모두 다른) 등
where : { id : { [Op.gte] : 4 } },
// order : 정렬, 배열안에 배열 구조
// order : [ [ 'id', 'DESC' ] ],
// limit : 가져올 개수
// limit : 1,
// offset : n개 건너뛰기
// offset : 1,
}).then((result)=> {
// console.log('result : ', result);
res.send(result); //배열형태로 send
});
}
SQL JOIN
두 개 이상의 테이블에서 데이터를 결합하여 새로운 결과 생성, 테이블 간 관계를 통해 정보를 얻어내야 할 때 JOIN을 사용하여 관련 데이터를 결합하고 원하는 정보 추출
CREATE TABLE user {
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
...
...
};
CREATE TABLE profile {
id INT PRIMARY KEY,
user_id INT,
introducd VARCHAR(100),
FOREIGN KEY (user_id) REFERENCES user(id)
};
//model
User.hasOne(Profile, { foreignKey : 'user_id' });
Profile.belongsTo(User, { foreignKey : 'user_id' });
hasOne()
- 한 모델이 다른 모델 가리키는 1:1관계 설정belongsTo()
- 다른 모델이 한 모델 가리키는 1:1관계 설정hasMany()
- 한 모델이 다른 모델과 1:N관계 설정belongsTo()
- 다른 모델이 한 모델 가리키는 1:N관계 설정CREATE TABLE Students {
...
...
};
CREATE TABLE Teachers {
...
...
};
CREATE TABLE StudentTeacherRelation {
...
...
FOREIGN KEY (StudentID) REFERENCES Students(StudentID),
FOREIGN KEY (TeacherID) REFERENCES Teachers(TeacherID)
};
//model
Student.belongsToMany(Teacher, { through : StudentTeacherRelation });
Teacher.belongsToMany(Student, { through : StudentTeacherRelation });
관계 설정 이후 Controller에서의 데이터 입력, 조회
export const enrollStudent = async (req, res)=> {
try {
const {userid, password, email, name, major, enroll} = req.body;
const user = await db.Student.create({
userid, password, email,
StudentProfile : {
name, major, enroll,
},
//include : 쿼리 실행할 때 관련된 모델 데이터도 함께 조회
}, { include : db.StudentProfile },
);
console.log(user);
} catch(error) {
console.log(error);
}
}
export const enrollClass = async (req, res)=> {
try {
const { name, room, code, professor, StudentId } = req.body;
const classes = await db.Classes.create({
name, room, code, professor, StudentId
})
} catch (error) {
}
}
export const getStudent = async (req, res) => {
try {
const student = await db.Student.findAll({
attributes : ['userid', 'email'],
include : [{ model : db.StudentProfile,
attributes : ['major', 'enroll']
}],
});
res.send(student);
} catch (error) {
console.log(error);
}
};