카테고리 없음

Sequelize(시퀄라이즈) : 방명록 실습을 바탕

DevOhwa 2022. 8. 10. 23:55
반응형

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 했어야했다.

mysql

근데 시퀄라이즈는 dataValues로 모든것을 싹 갖고오는것이다. 

  let newObj ={
        name : req.body.name,
        comment : req.body.comment
    };

시퀄라이즈는  위 와같이 적어주기만 해도 data를 가져와 보여준다. 

시퀄라이즈

→ 배열이 담겨오지 않기 때문에 우리가 id: result.id로바로 검색이 가능한 것이다.

배열안에 있었으면 result[n].id 이런식으로 인덱스 지정 후 불러올 수 있다. 

 

 

Controller의 update와 destroy에서의  result

콘솔로그에서 내가 수정했거나, 삭제한 부분들이 몇개인지 콘솔로 보여준다. 

 

 

 

 

 

 

* 피드백 반영완~! 피드백 환영합니다!