속편: SQL용 Mongose


소개


MEAN이나 MERN stack 응용 프로그램을 개발한 모든 사람들은 Mongoose에 익숙할 것이다. 이것은 유용한 대상 데이터 모델링 라이브러리로 몬고DB를 더욱 쉽게 사용할 수 있다.이 응용 프로그램 창고는 매우 유행하기 때문에 약 1000개의 강좌 (그중 일부는 훨씬 낫다) 가 몬고 DB, Express, React (또는Angular) 와 Node를 어떻게 사용하는지 보여 준다.js 같이 있어요.
그러나 MySQL (또는 SQLite, PostgreSQL 또는 그 어떠한 유형의 SQL 데이터베이스) 을 사용하여 간단한 풀스택 응용 프로그램을 구축하기로 결정했을 때, 나는 Express와 Node를 어떻게 사용하는지 거의 의미가 없다는 것을 발견했다.진정으로요즘 별일 없어요?숙고되지 않은 모듈식 아키텍처?아무도 이 일을 할 좋은 방법이 없는 것 같다 - server.js 파일에 기록된 실제 SQL 조회 외에 데이터베이스에 대한 생성, 읽기, 업데이트 및 삭제(CRUD) 작업을 수행할 수 있는 내용은 없습니다.
그리고 Sequelize을 찾았습니다. 모든 것이 변했습니다.
나는 여기서 배운 것을 공유하고 싶다. 많은 유행이 지난 강좌에서 다른 사람들을 구할 수 있기를 바란다. 왜냐하면 Sequelize가 자신의 노드 응용 프로그램에서 SQL 데이터베이스를 실현하는 것을 얼마나 쉽게 할 수 있는지 모르기 때문이다.

Sequelize란 무엇입니까?


Sequelize 홈 페이지에서 가장 정확하게 요약한 내용은 다음과 같습니다.

Sequelize is a promise-based ORM for Node.js v4 and up. It supports the dialects PostgreSQL, MySQL, SQLite and MSSQL and features solid transaction support, relations, read replication and more.  -  Sequelize


이것은 내가 발견한 자바스크립트 응용 프로그램에서 SQL을 사용하여 데이터베이스를 처리하는 가장 간단하고 직접적인 도구이다.유사한 기능을 제공하는 다른 옵션도 있다.나는 Knex.js을 생각했지만 그들의 GitHub 통계 데이터를 비교한 후에 Sequelize를 선택했다.

왜 특별히 속편을 해야 합니까?


다음은 내가 결정하는 데 도움을 주는 통계 데이터들이다.
  • Sequelize는 8000여 개의 제출(Knex는 2000개 미만),
  • 375개 방출(Knex 119개),

  • 공헌자 694명(Knex 237명),
  • 최근 베타 버전 5(Knex는 v0.15에서),
  • 발표
  • , CLI, TypeScript 및 GraphQL 통합(Knex 없음),
  • NPM에서 월
  • 회 다운로드 및 883000회 (Knex의 월 다운로드 수는 600000회 이하)
  • 거의 모든 면에서 Sequelize는 Knex보다 우수하기 때문에 저는 매우 안정적이고 문서 기록이 양호하며 장기적으로 유지보수되고 자주 업데이트되는 라이브러리를 사용하기로 결정했습니다.
    제가 말하고자 하는 것은 Knex가 원생 Oracle과 Amazon Redshift 지원을 제공했지만 Oracle DB를 사용하지 않으려고 하기 때문에 이것은 저에게 주요한 판매점이 아닙니다.

    속편은 족제비에 비해


    따라서 Sequelize를 사용하면 Mongose가 MongoDB 사용자에게 제공하는 것과 같은 유형의 장점과 보너스를 많이 얻을 수 있습니다.
  • 다양한 유형의 SQL 데이터베이스에 연결하는 능력,

  • 대상 모델(족제비 모델과 유사), 유형화, 표에 비추고 필요할 수 있음,
  • 기본 및 고급 조회 옵션, 예를 들어 findAll/findOne, destroy, update 등, 페이지 나누기, 끼워넣기 대상과 관련,

  • 연결 풀,

  • 원본 조회,
  • 과 그 이상을 보도할 시간이 없습니다.
  • documentation은 매우 철저하다. 이것은 속편이 얼마나 많이 제공될 수 있는지를 보여 준다. 반드시 스스로 그것을 관리해야 하는 것이 아니라.
    Sequelize를 사용하면 데이터베이스 사투리의 미세한 변화에 적응하기 위해 SQL 조회를 다시 쓰는 번거로움을 줄일 수 있음을 지적하고 싶습니다 -  어떤 유형의 데이터베이스에 연결되든지 간에 당신의 findcreate 문장은 수정할 필요가 없이 작업할 수 있습니다.나는 네가 어떻게 생각하는지 모르겠지만, 나는 그렇게 노력하지 않는 팬이다.
    Sequelize는 Bluebird을 통해promises를 사용하여 비동기 제어 흐름을 제어합니다.이것은 Sequelize를 통해 데이터베이스를 조회할 때 이 약속을 되돌려준다는 것을 의미합니다.
    User.findOne().then(user => {   
        console.log(user.get('firstName')); 
    });
    
    // returns user object's first name, like 'John'
    
    이것 또한 Sequelize가 ES6 async/await 기능과 잘 어울려 사용할 수 있다는 것을 의미한다.
    user = await User.findOne();  
    
    console.log(user.get('firstName'));
    
    // also returns user object's first name, like 'John'
    

    Express에서 Sequelize를 구현하는 방법회사 명


    좋습니다. 이제 Sequelize를 사용하는 이유를 보실 수 있습니다. 프로젝트에서 어떻게 사용하십니까?
    내가 견본이나 교과서를 볼 때마다 이것은 항상 나의 가장 큰 문제이다.어떻게 사용해야 합니까?나는 어떻게 나의 파일과 프로그램 구조를 조직해야 나의 이 방면에서 최소한의 수정을 하는 상황에서 교환 기능을 쉽게 할 수 있습니까?
    이것은 내가 제시한 원본 파일 구조(서버(API) 폴더만 포함)이다.이것은 매우 간단하다. 왜냐하면 내가 시도한 프로젝트는 결코 특별히 복잡하지 않기 때문이다.그러나 루트 폴더를 통해 CRUD 기능을 추가하는 것이 쉬워지고 모델 폴더로 인해 데이터베이스 모델을 하나 이상 정의하는 것도 좋습니다.
    root/
    ├── api/ 
    | ├── server.js 
    | ├── sequelize.js 
    | ├── package.json
    | ├── models/ 
    | | ├── user.js
    | ├── routes/ 
    | | ├── deleteUser.js 
    | | ├── findUser.js 
    | | ├── loginUser.js 
    | | ├── registerUser.js
    | | ├── updateUser.js
    | ├── data/ (optional depending on storage choice - like SQLite) 
    | | ├── db/ 
    | | | ├── storage.sqlite
    | ├── node-modules/
    
    이제 파일 구조를 보았습니다. 파일이 어떤 내용을 포함하는지 보여 드리겠습니다.user.js 파일로 시작하겠습니다. sequlize.jsroutes 파일로 가져오기 때문입니다.

    모델 정의


    다음은 사용자 모델의 코드입니다.user.js
    module.exports = (sequelize, type) => {
      return sequelize.define('user', {
        id: {
          type: type.INTEGER,
          primaryKey: true,
          autoIncrement: true
        },
        first_name: type.STRING,
        last_name: type.STRING,
        email: type.STRING,
        username: {
          type: type.STRING,
          allowNull: false
        }, 
        password: {
          type: type: STRING,
          allowNull: false
        }
      })
    };
    
    user registration application을 구축하고 있기 때문에 사용자 모델 파일은 매우 간단합니다.기본 키로 설정되어 자동으로 증가하는 ID일 뿐입니다. 이름, 성, 전자메일, 사용자 이름, 비밀번호 (둘 다 필요합니다.)이것은 이해하기 쉽다.

    데이터베이스 연결 설정


    다음은 sequelize.js 파일입니다. 이것은 제가 대부분의 데이터베이스 설정을 저장한 곳입니다. 만약에 MySQL 데이터베이스에서 SQLite 데이터베이스로 이전하고 싶다면 데이터베이스를 쉽게 전환할 수 있습니다.다음은 MySQL 연결의 모양입니다.sequelize.js
    import Sequelize from 'sequelize';
    import UserModel from './modes/user';
    
    const sequelize = new Sequelize('dbname', 'admin', 'password', {
      host: 'db',
      dialect: 'mysql'
    });
    
    const User = UserModel(sequelize, Sequelize);
    
    sequelize.sync()
      .then(() => {
        console.log('Users db and user table have been created');
      });
    
    module.exports = User;  
    
    보시다시피 우선 sequelize 변수를 사용하여 MySQL 데이터베이스에 연결을 시작하고 데이터베이스 이름, 사용자 이름, 비밀번호를 지정한 다음에 호스트와 사투리를 지정합니다.그게 다야.
    그리고 저는 이전에 정의한 user모델을 추가했습니다. sequelize.sync() 함수는 모든 정의된 모델을 데이터베이스에 동기화합니다.이런 방식을 통해 사용자가 제공한 정보와 그 모델에 따라 데이터베이스와 테이블을 만들 수 있습니다.
    마지막으로, 나는 프로젝트의 다른 부분, 예를 들어 노선에 사용할 수 있도록 앞에서 정의한 User 상량을 내보냈다.
    다음은 SQLite 연결의 또 다른 예입니다. 차이점은 다음과 같습니다.sqliteSequelize.js
    import Sequelize from 'sequelize';
    import UserModel from './modes/user';
    
    const sequelizeSqlite = new Sequelize('dbname', 'admin', 'password', {
      host: 'sqlite',
      dialect: 'data/db/storage.sqlite'
    });
    
    const UserSqlite = UserModel(sequelizeSqlite, Sequelize);
    
    sequelizeSqlite.sync()
      .then(() => {
        console.log('Users db and user table have been created with Sqlite');
      });
    
    module.exports = UserSqlite;  
    
    SQLite 데이터베이스에 대한 간단한 연결은 프로젝트 자체에 저장됩니다.
    데이터베이스 설정에 대한 미세한 변경 사항을 제외하고 파일의 다른 내용은 변하지 않습니다.

    노선 정의


    네, 거의 설정을 마쳤습니다.
    코드 모듈화를 유지하고 (응용 프로그램에서 기능을 추가하거나 삭제하기 쉽게) CRUD 기능의 모든 부분을 단독 파일로 데이터베이스에 추가합니다.동일한 파일에 모두 추가할 수 있으며, 모델이나 가장 쉽게 조직을 유지할 수 있는 방식에 따라 구분할 수 있습니다.
    다음은 제 사용자 등록 노선 예시 (창설 기능) 입니다.나는 bcrypt 을 사용하여 비밀번호를 추가했지만, 지금은 중요하지 않다.registerUser.js
    import User from '../sequelize';
    import bcrypt from 'bcrypt';
    
    const BCRYPT_SALT_ROUNDS = 12;
    
    module.exports = (app) => {
      app.post('/registerUser', (req, res) => {
        const data = {
          fist_name: req.body.first_name,
          last_name: req.body.last_name,
          email: req.body.email,
          username: req.body.username,
          password: req.body.password
        };
    
        if(data.password === '' || data.username === ''){
          res.json('username and password required');
        }
        User.findOne({
          where: {
            username: data.username
          }
        })
        .then(user => {
          if (user !== null) {
            console.log('username already taken');
            res.json('username already taken');
          } else {
            bcrypt.hash(data.password, BCRYPT_SALT_ROUNDS)
            .then((hashedPassword) => {
              User.create({
                first_name: data.first_name,
                last_name: data.last_name,
                email: data.email,
                username: data.username,
                password: hashedPassword
              })
            })
            .then(() => {
              console.log('user created');
              res.json('user created');
            })
          }
        })
        .catch(err => {
          console.log('problem communicating with db');
          res.status(500).json(err);
        })
      })
    };
    
    위의 코드를 통해 알 수 있듯이 사용자 모델은 sequelize.js 파일에서 가져온 것이다. 사용자 입력 데이터는 응용 프로그램의 클라이언트가 req.body.xyz 필드를 통해 전달된 것이다. 그리고 새로운 사용자를 추가하기 전에 나는 Sequelize를 빌려 데이터베이스를 여러 차례 검사했다.
    첫 번째 검사는 사용자가 사용자 이름과 비밀번호를 동시에 제공하는지 확인하는 것입니다. (모델의 요구에 따라) 사용자 이름과 비밀번호가 거기에 없으면 서버는 오류 메시지 'username and password required'을 되돌려줍니다.
    검사 후, 나는 데이터베이스를 조회하여 이 사용자 이름이 점용되었는지 확인하고, 만약 점용되었다면, 서버는 다시 'username is already taken'을 클라이언트에게 보낼 것이다.
    이 검사를 통과하면 암호가 산열되고 사용자 정보는 데이터베이스에 저장됩니다.저장에 성공하면 클라이언트 'user created'에 성공 메시지를 보냅니다.
    전체 창설 작업은 패키지로 되어 있기 때문에 서버와 통신하는 데 문제가 발생하면 (서버 종료, 네트워크 문제 등) 클라이언트에게 메시지를 보내서 클라이언트에게 문제가 발생했음을 알릴 수 있습니다.

    서버에 라우팅 추가


    현재, 나는 이 루트들을 서버에 추가하려고 한다.이것은 가장 간단한 부분이다.server.js
    import express from 'express';
    import Cors from 'cors';
    import bodyParser from 'body-parser';
    import logger from 'morgan';
    
    const app = express();
    
    app.use(Cors());
    app.use(bodyParser.urlencoded({ extended: true }));
    app.use(bodyParser.json());
    app.use(logger('dev'));
    
    require('./routes/loginUser')(app);
    require('./routes/registerUser')(app);
    require('./routes/findUsers')(app);
    require('./routes/deleteUser')(app);
    require('./routes/updateUser')(app);
    
    app.listen(API_PORT, () => console.log(`Listening on port ${API_PORT}`));
    
    module.exports = app;
    
    당신이 해야 할 일은 나처럼 server.js 파일의 루트를 필요로 하고 그것들을 당신의 Express 응용 프로그램에 넣으면 완성할 수 있습니다.이보다 더 간단한 것은 없다.
    이제 Sequelize를 노드의 모든 유형의 SQL 데이터베이스에 사용할 수 있어야 합니다.js, Express 프로젝트.
    Sequelize를 사용하는 전체 MERN 스택 예시를 보려면 Repo here을 보십시오.주 지점에서 docker-compose build을 실행한 다음 docker-compose up을 실행할 수 있으며, sqlite 기능 지점에서 npm startapi/ 폴더의 client/을 사용하여 각각 클라이언트와 서버 파일을 시작할 수 있습니다.

    결론


    Sequelize는 JavaScript 응용 프로그램에서 SQL 데이터베이스를 사용하는 데 질서와 유연성을 제공합니다.그것은 원본 조회 작성, 연결 관리, 유해 SQL 공격 방지 등의 수요를 감소시켰다.기본적인 설정을 통해 JS 프로젝트에서Sequelize를 사용할 수 있습니다 - 당신의 개발 시간을 가속화시킬 수 있기를 바랍니다.나는 반드시 이 공구를 계속 사용할 것이다.
    몇 주 후에 다시 돌아올게요. 자바스크립트, React, 사물인터넷 또는 웹 개발과 관련된 내용을 더 많이 쓸게요.
    만약 당신이 영원히 한 편의 문장을 놓치지 않을 것을 확보하고 싶다면, 여기에 나의 시사통신을 등록하세요: https://www.paigeniedringhaus.substack.com
    읽어 주셔서 감사합니다. 이것은 당신의 미래 데이터베이스 드라이브 프로젝트에 도움이 되기를 바랍니다.

    참고 자료 및 기타 자료

  • MongooseJS
  • Sequelize
  • Knex.js
  • bcrypt
  • GitHub 환매 MERN app using Sequelize
  • 좋은 웹페이지 즐겨찾기