본문 바로가기

Node.js

Node.js(17) - 모델 생성 방법(User: define 함수 / Comment: class 활용), sequelize를 활용한 CRUD 구현

728x90
반응형

1) Node.js

   1-1) 모델 생성 방법 - User(define 함수 활용), Comment(class 활용)

   1-2) sequelize를 활용한 CRUD 구현

 

 

 

 

 

 

 

 

1) Node.js

1-1) 모델 생성 방법 - User(define 함수 활용), Comment(class 활용)

Sequelize
express 기본세팅을 먼저 한 뒤 Sequelize 기본세팅을 진행함!

 

$ npm init -y
$ npm install express cors mysql2 sequelize dotenv



server.js

const express = require("express");
const app = express();

app.listen(3000, () => {
  console.log(`server start`);
});



config.js

require("dotenv").config();

const config = {
  env: process.env.NODE_ENV || "development",
  port: process.env.PORT || 3000,
  db: {
    development: {
      username: process.env.DB_USER || "",
      password: process.env.DB_PASSWORD || "",
      database: process.env.DB_DATABASE || "",
      port: process.env.DB_PORT || "",
      host: process.env.DB_HOST || "",
      dialect: "mysql",
    },
  },
};

module.exports = config;

 

 

.env

PORT=3000
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=본인 user명
DB_PASSWORD=본인 MySQL 비밀번호
DB_DATABASE=sequelize
NODE_ENV=development

 

 


백엔드 서버를 만들 때 순서
(1) 기획
(2) 데이터베이스 테이블 설계
(3) API(라우터 세팅)
--> 이후부터 작업 가능하다!(이때부터 express 코드를 작성할 수 있음!)

 

 

Sequelize 세팅
(1) models 디렉토리 생성

  • DB Connection과 관련된 파일: index.js
  • Model에 대한 파일들: Model
    • 데이터베이스를 기준으로 Table에 있는 field 내용을 객체로 표현한 것들을 의미함
    • 객체로 표현하기 힘든 1:N 관계를 표현할 수 있음

(2) Sequelize-cli(터미널에서 sequelize를 조작하는 것): sequelize init

 

 

 

 

back

server.js

const express = require("express");
const config = require("./config");
const { sequelize } = require("./models");
const app = express();
const PORT = config.port;

app.use(express.json());

app.use((error, req, res, next) => {
  res.send("ERROR");
});

app.listen(PORT, async () => {
  await sequelize.sync({ force: true });
  console.log(`server start ${PORT}`);
});

 

 

config.js

require("dotenv").config();

const config = {
  env: process.env.NODE_ENV || "development",
  port: process.env.PORT || 3000,
  db: {
    development: {
      username: process.env.DB_USER || "",
      password: process.env.DB_PASSWORD || "",
      database: process.env.DB_DATABASE || "",
      port: process.env.DB_PORT || "",
      host: process.env.DB_HOST || "",
      dialect: "mysql",
    },
  },
};

module.exports = config;

 

 

models/index.js

const Sequelize = require("sequelize"); // Sequelize의 데이터 타입: function(정확히는 class를 의미함)
const config = require("../config");
const db = config.db[config.env]; // "const db = config.db["development"]"와 동일한 의미이다!

// 인자값으로 database명, username, password가 들어감!
// mysql은 TCP 통신을 하는데 이때 TCP 통신 시 중요한 식별자에는 port, host가 있다!
const sequelize = new Sequelize(db.database, db.username, db.password, db);

// user.model.js
require("./user.model.js")(sequelize, Sequelize);

// sequelize.models.User = {}

// const user = require("./user.model.js")(sequelize, Sequelize);
// console.log(user === sequelize.models.User) // true

// comment.model.js
// class의 개념 중 "정적 메서드"가 있는데 이것의 동작원리를 살펴볼 예정
const Comment = require("./comment.model.js")(sequelize, Sequelize);
// console.log(sequelize.models);
// console.log(sequelize.models.Comment === Comment); // true

// const Comment = require("./comment.model.js");
// Comment.initialize(sequelize, Sequelize);

module.exports = {
  sequelize,
  Sequelize,
};

 

 

models/user.model.js(define 함수 활용)

module.exports = (sequelize, DataTypes) => {
  return sequelize.define(
    "User",
    {
      userid: {
        type: DataTypes.STRING(30),
        allowNull: false,
        unique: true,
      },
      userpw: {
        type: DataTypes.STRING(64),
        allowNull: false,
      },
      username: {
        type: DataTypes.STRING(30),
        allowNull: false,
      },
      gender: {
        type: DataTypes.STRING(2),
        defaultValue: "남자",
      },
    },
    {
      freezeTableName: true, // 이 코드를 실행시키지 않으면 위에서 지정한 table 이름("User")에 자동으로 "s"가 뒤에 붙어서 table이 만들어진다!!
      // modelName: "zxcv",
      // tableName: "zxcv", // 이 코드를 실행시키면 새로 생성한 table 이름이 위에서 정의한 "User"가 아닌 "zxcv"가 된다!!
      timestamps: false,
      charset: "utf8mb4",
      callate: "utf8mb4_general_ci",
    }
  );
};

 

 

models/comment.model.js(class 활용)

module.exports = (sequelize, Sequelize) => {
  class Comment extends Sequelize.Model {
    static initialize() {
      return this.init(
        {
          userid: {
            type: Sequelize.STRING(30),
            allowNull: false,
          },
          content: {
            type: Sequelize.TEXT(),
            allowNull: false,
          },
        },
        {
          sequelize: sequelize,
          freezeTableName: true,
        }
      );
    }
  }

  return Comment.initialize(); // define 함수와 동일한 결과를 반환함!
};

/*
const Sequelize = require("sequelize");

// init 함수는 define 함수와 동일한 역할을 수행한다!
class Comment extends Sequelize.Model {
  static initialize(sequelize, DataTypes) {
    this.init(
      {
        userid: {
          type: DataTypes.STRING(30),
          allowNull: false,
        },
        content: {
          type: DataTypes.TEXT(),
          allowNull: false,
        },
      },
      {
        sequelize: sequelize,
        freezeTableName: true,
      }
    );
  }
}

// Comment --> [[prototype]] --> init
// init 함수: 첫번째 인자값 - field 정보, 두번째 인자값 - table + sequelize
// Comment.init(
//   {
//     userid: {
//       type: Sequelize.STRING(30),
//       allowNull: false,
//     },
//     content: {
//       type: Sequelize.TEXT(),
//       allowNull: false,
//     },
//   },
//   {
//     sequelize: sequelize,
//     freezeTableName: true,
//   }
// );

module.exports = Comment;
*/

 

 

.env

PORT=3000
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=본인 user명
DB_PASSWORD=본인 MySQL 비밀번호
DB_DATABASE=sequelize
NODE_ENV=development

 

 

+) class 예시코드

class Person {
  // 접근 제어자(Javascript 신문법) --> public(객체 생성 시 속성명이 console에 찍었을 시 다 보이는 것을 의미함), private(속성을 만들어서 사용은 하지만 console에 찍었을 시 안 보이게 하는 것을 의미함)
  // private을 설정하는 방법: 해당 속성 앞에 "#"을 붙임(해당 문법은 Javascript에서만 사용 가능함)
  #key = 180;
  constructor(_name, _age) {
    this.name = _name;
    this.age = _age;
  }

  // getName() {
  //   const a = this.#key + this.name;
  //   return a;
  // }

  // 정적 메서드로 지정히고 싶다면 해당 메서드 앞에 "static"을 붙이면 됨!!
  static getName() {
    // const a = this.#key + this.name;
    // return a;
    return "hello";
  }

  // static setDate(now) {
  //   console.log(this);
  //   return "시분초" && "날짜";
  // }
}

class Sangbeom extends Person {
  constructor(_age) {
    super("sangbeom", _age);
  }

  // Sangbeom class에서 getName 메서드를 찾는 경우(this, super의 경우를 각각 아래와 같이 살펴봄)
  // this.getName(): this --> Sangbeom --> [[prototype]] --> getName
  // super.getName(): super --> Person --> getName
  static name() {
    console.log(super.getName());
    // console.log("hello");
    // return
  }

  getName() {
    console.log(this);
  }
}

// Person.setDate(Date.now());
// const person = new Person("sangbeom", 28);
// console.dir(person);
// console.log(person);
// const a = person.getName(); // 이 코드는 getName 메서드가 동적 메서드일 때만 실행 가능하다!!
// console.log(a);

const sangbeom = new Sangbeom(28);
console.log(Sangbeom.name());

// 동적 메서드: 인스턴스 안에 있는 메서드
// 정적 메서드: 인스턴스 그 자체를 가리키는 메서드
// (중요!!) 정적 메서드는 인스턴스를 생성할 필요 없이 바로 사용 가능하다!!

// console.log(Buffer);

 

 

 

 

1-2) sequelize를 활용한 CRUD 구현

※ CRUD의 경우, 빠른 확인을 위해 server.js에서 실행 여부를 바로 확인하도록 함(나머지 코드 파일은 위와 동일하여 생략함)

 

server.js

const express = require("express");
const config = require("./config");
const { sequelize } = require("./models");
const app = express();
const PORT = config.port;

app.use(express.json());

app.use((error, req, res, next) => {
  res.send("ERROR");
});

app.listen(PORT, async () => {
  await sequelize.sync({ force: true });
  // console.log(sequelize.models); // User, Comment
  const Comment = sequelize.models.Comment;
  
  // Create
  // INSERT INTO Comment(userid, content) VALUES('hsb7722', 'hello sequelize~~');
  const insert = await Comment.create({
    userid: "hsb7722",
    content: "hello sequelize~~",
  });
  console.log(insert);

  const insert2 = await Comment.create({
    userid: "2222hsb",
    content: "hello world2222",
  });
  const insert3 = await Comment.create({
    userid: "3333hsb",
    content: "hello world3333",
  });
  const insert4 = await Comment.create({
    userid: "4444hsb",
    content: "hello world4444",
  });

  // Read
  // SELECT * FROM Comment;
  const selectAll = await Comment.findAll();
  // SELECT * FROM Comment WHERE userid='hsb7722' LIMIT 1;
  const selectOne = await Comment.findOne({ where: { userid: "hsb7722" } }); // 만약 where 조건에 맞는 것이 없으면 "null"을 반환함!
  console.log(selectAll);
  console.log(selectOne);

  // Update
  // UPDATE Comment SET userid='qwer7722', content='수정~~!!' WHERE id=2;
  // 첫번째 인자값: 바꿀 내용들, 두번째 인자값: where
  const update = await Comment.update(
    {
      userid: "qwer7722",
      content: "수정~~!!",
    },
    {
      where: { id: 2 },
    }
  );
  console.log(update);

  // Delete
  // DELETE FROM Comment WHERE id=3;
  const destroy = await Comment.destroy({ where: { id: 3 } });
  console.log(destroy);

  // query문 또한 사용 가능하다!
  const [query] = await sequelize.query("SELECT * FROM Comment");
  console.log(query);

  console.log(`server start ${PORT}`);
});