220810수요일. 시퀄라이즈
갓규리쌤과 폭우대비 비대면 수업.
비대면수업하면 좋겠다고 생각했는데, 집에있는거 빼고 싹다 단점뿐이었다. 각설하고... 이해한만큼 써보겠다.
시퀄라이즈 sequelize
자바스크립트에서 사용하면 알아서 sql문을 실행한다.
→ 왜쓰나?
어떤 데이터베이스를 사용하느냐에 따라서 달라지는데, 시퀄라이즈가 알아서 변환을 해준다. 다른 데이터베이스로의 전환도 유용하게 할 수 있다.
실제로 써보는것이 베스트
npm install sequelize-cli mysql2
npm sequelize init
위의 두개를 먼저 설치해준다.
config를 만들어준다.
host랑 user등을 사용하지 않고, config에서 다 해주기 위해서이다. config에 다해주면 파일들을 모듈안에서 찾아다니면서 바꿔줘야할 이유가 사라진다.
config - config.json
폴더: config → 파일: config.json을 만들어준다.
{
"development" :{
"host": "localhost",
"database": "sesac",
"username": "user",
"password": "****",
"dialect": "mysql"
},
"production" :{
},
"test" : {
}
}
json은 우리눈에 딕셔너리 형태로 보인다. 위처럼 config.json을 작성한다.
위와 같은 작업을 해줌으로써 mysql사용할때처럼 const cnn등을 사용할 필요가 없어졌다.
시퀄라이즈는 model폴더에 index.js를 만들어주어야한다.
왜...였는지는 못들었다. ..
Model폴더 - index.js
const Sequelize = require("sequelize");
const config = require("../config/config.json")["development"];
//const a require(../config/config.json);
//const a {"development" : {}
const db = {};
const sequelize = new Sequelize(
config.database,
config.username,
config.password,
config
);
db.sequelize = sequelize;
db.Sequelize = Sequelize;
db.Visitor = require("./Visitor")(sequelize, Sequelize);
//함수를 실행한거임. 위의 코드는 model/Visitor.js에서 함수가 실행되고 return된 model.
//const a = require("./Visitor")((sequelize, Sequelize)): 이게 위의 한줄의 코드임.
// require("./Visitor") .Visitor에서 modeul.exports에 잇는것을 가져온거임.
//근데 Visitor는 함수임. const Visitor는 함수를 가져오고 실행을 시키겠다는뜻임.
module.exports = db;
//실행을 하고나면 model이 오니까 컨트롤러 마지막 코드 module에 함수가 담긴것.
// --> 이부분은 내가 적었지만 뭐라는지 모르겠다.
model의 index.js에 위와 같이 선언을 해준다.
위의 코드 중에 config 파일에 데이터 베이스 정보를 저장하지 않았다면
config부분에 { "host": "localhost", "database": "sesac"}
이런식으로 적어주어야한다. 하지만 config에서 적어줬기때문에 그러지 않아도 된다.
→ Sequelize는 왜 내보내나요?
(질문의 의도 : 위의 코드에서 seauelize(소문자s)는 우리가 쓰려고 생성해준 객체이기 때문에 당연히 export해주어야하지만, Sequelize(대문자)는 왜 내보내야 하는가?)
Sequelize를 require했을때, datatypes를 이용하고 싶다거나 등등의 이유로 시퀄라이즈를 내보내고, sequelize.dataTypes 등으로 이용 할 수 있다. 똑같이 require하지 않도록 보내준다.
미리 모든 경우를 대비한다고 생각하면 된다. 안쓰더라도 일단 내보내준다.
위의 index.js에서 모든 작업을 미리 해둔다고 생각하면 편하다.
시퀄라이즈 문법을 쓸때는 항상 model이 존재해야한다. 모델 = 테이블 구조
테이블 구조 정의 : Sequelize 모델 정의
Sequelize.define( (1)인자, (2)인자, (3)인자 );
1) 모델(테이블) 이름 설정
2) 컬럼 정의
3) 모델의 옵션 정의
Model 폴더속의 Visitor.js
const Visitor = ( Sequelize, DataTypes ) =>{
const model = Sequelize.define(
'visitor',
{
// create ~~ (id int not null primary key, auto_increment 등등이 있는데 우리가
//테이블 만든거랑 동일해야한다. )
id:{
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name:{ //name varchar(10) not null
type: DataTypes.STRING(10),
allowNull: false,
},
comment:{ //comment mediumtext, 만약 내가 logtext였다면 medium대신long을 쓴다.
//not null 없으면 true쓰거나 그냥 안써도 된다.
type: DataTypes.TEXT('medium')
}
},
{
timestamps: false,
//ture로 지정하게 되면 등록된 사건과 수정된 시간을 갖는 칼럼이 만들어진다.
//자동으로 타임스탬프를 찍으려 하는데, 그걸 막는거임 우리컬럼에는 그런게 없으니까 false
참고로 timestamps에 s 빼먹지 말것.
tableName: 'visitor',
freezeTableName: true,
//이름을 복수로 정의하지 않는다.모델이름에 다 s를 붙이려한다. 시퀄라이즈 특징이다.
//이걸 true로 하면 복수로 설정하지 않는다. 테이블이름을 바꾸지말라 설정해주는것이다.
}
);
return model;
//위에서 만든친구들을 내보낸다.
//리턴한 친구들은 model - index.js. 거기에 있는
//db.Visitor = require("./Visitor")(sequelize, Sequelize); 여기로 간 것.
}
module.exports = Visitor;
→ visitor의 칼럼은 id, name, comment 3가지다라고 나타낸것이다.
Controller
//주석처리 된 코드들은 mysql에서 기존에 쓰던것과 비교하기 위해서 남겨두었다.
const models = require("../model");
//models => Visitor의 모델이다.
exports.get_visitors = (req,res) => {
models.Visitor.findAll()
//findAll() : 시퀄라이즈 문법이고, promise(result)로 받을 수 있는것.
//함수가 어떤 함수인지만 알면 알아서 처리한다.
//참고로 여기서 findAll(); <--이렇게 마침표찍어서 .then 이 실행이 안됐었다. ! 주의요망.
//findAll 은 sequelize문법임 Select* from visitor; 알아서 이런 같은역할을 함.
//findall: where 설정 가능. 그냥 조건에 만족하는 여러 정보를 다 가져온다는것.
.then((result) => {
console.log( "index" );
console.log( result[0] );
console.log( result[0].id );
res.render("index", { data: result });
});
}
exports.post_comment = (req,res) => {
// console.log( req.body );
// Visitor.insert( req.body.name, req.body.comment, function( result ){
// res.send({ id: result });
// } );
let object= {
name: req.body.name,
comment:req.body.comment
}
//create() -> insert into visitor
//create({nmae:'hong', comment:'gildong'})
//-> insert into visitor(name, comment) values('hong','gildong')
models.Visitor.create(object)
//create안에는 어떤 객체인지()안에 꼭 넣어주어야한다. promise니까 당연히 then사용
.then((result) => {
//res.rend
console.log(result);
res.send({id: result.id});
})
}
//get_visitor는 하나의 데이터만 검색을 한거임
exports.get_visitor = (req,res) => {
//select*from visitor where id = req.qurey.id limit 1
models.Visitor.findOne({
//one은 하나만 찾으니까 조건이 필요한거임. 함수가 리턴하는 방식의 차이all과 one
//findone 은 visitor 에서 하나만 적혀서 온거임. findall은 배열에 담겨서 온다. one 은 하나의 data만옴.
where:{ id: req.query.id, name:"홍길동"}
//where에서 ,를 사용하면 and조건이 되는거임.
}).then((result) => {
console.log( result );
res.send( {result : result} );
})
// Visitor.get_visitor( req.query.id, function(result) {
// console.log( "result : ", result );
// res.send( { result : result[0] } );
// =>>위랑 비교해서 봐봐, mysql은 항상[]으로 오는 배열이었잖아. 근데 시퀄라이즈는 아닌거임.
}
exports.patch_comment = (req,res) => {
// Visitor.update( req.body, function(result){
// console.log( result );
// res.send( "수정 성공" );
// });
//업데이트하니까 update 함수를 사용함. 업데이트는 내가 수정할 내용을 보내준다.
let newObj ={
name : req.body.name,
comment : req.body.comment
};
//첫번째로 내가 바꾸고자하는 내용을 적어준다. newObj, 그리고 조건
//update visitor ser name=req.body.name, comment : req.body.comment where id = req.body.id;
//아래의 문법만 잘 기억하면 업데이트는 쉽다.
models.Visitor.update( newObj, {where: { id: req.body.id}})
.then((result) =>{
//promise니까 업데이트 성공했다면 result 찍고 수정성공 보내라
console.log( result );
res.send('수정성공');
})
}
exports.delete_comment = (req,res) => {
// Visitor.delete( req.body.id, function(result){
// console.log( result );
// res.send( "삭제 성공" );
models.Visitor.destroy({
where: { id: req.body.id }
//여기의 where은 뭘까(where : id=req.body.id)
// -> 이친구와 update는 내가 몇개를 업뎃하고 삭제하는지 갯수를 보내준다.
//우리가 정하는게 아니라 그냥 그 함수들의 특징임. 그렇게 리턴을 해준다.
}).then((result) => {
console.log( result );
res.send("삭제성공");
})
}

exports.get_visitors = (req,res) => {
models.Visitor.findAll()
.then((result) => {
// console.log( "result : ", result );
console.log( "index" );
console.log( result[0] );
console.log( result[0].id );
res.render("index", { data: result });
});
}
시퀄라이즈에서 온건 dataValues값을 바로 찾아준다.
반면에 mysql은 insertId랑 내가 무슨 작업을 했었는지 okpacket을 통해서 보내줬었다. 그럼 그때의 id값을 가지고 세부데이터를 또한번 찾아나섰어야 했는데, 시퀄라이즈는 직관적으로 보여준다.
다른예시를 또 적자면,
만약 table에 defaul가 설정되어있다.
name, comment, age라는 컬럼이 존재한다. insert했을때 age 컬럼의 값을 알 수 있는가? 없다.
기존의 mysql은 insert하면 insert된 결과를 알려준다. 그래서 받아온 정보들을 가지고 age를 알고 싶었다면 다시한번 정보를 select 했어야했다.

근데 시퀄라이즈는 dataValues로 모든것을 싹 갖고오는것이다.
let newObj ={
name : req.body.name,
comment : req.body.comment
};
시퀄라이즈는 위 와같이 적어주기만 해도 data를 가져와 보여준다.

→ 배열이 담겨오지 않기 때문에 우리가 id: result.id로바로 검색이 가능한 것이다.
배열안에 있었으면 result[n].id 이런식으로 인덱스 지정 후 불러올 수 있다.
Controller의 update와 destroy에서의 result
콘솔로그에서 내가 수정했거나, 삭제한 부분들이 몇개인지 콘솔로 보여준다.
* 피드백 반영완~! 피드백 환영합니다!