์ƒ์„ธ ์ปจํ…์ธ 

๋ณธ๋ฌธ ์ œ๋ชฉ

[๋…ธ๋“œ 2ํŒ€] #8. MySQL

24-25/Node.js 2

by sksmsyena 2024. 11. 29. 10:00

๋ณธ๋ฌธ

728x90

๐ŸŒŸํ‚ค์›Œ๋“œ: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, MySQL, CRUD, Sequelize, ๋ชจ๋ธ


1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค

- ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค: ๊ด€๋ จ์„ฑ์„ ๊ฐ€์ง€๋ฉฐ ์ค‘๋ณต์ด ์—†๋Š” ๋ฐ์ดํ„ฐ๋“ค์˜ ์ง‘ํ•ฉ

- DBMS: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ฆฌ ์‹œ์Šคํ…œ

- RDBMS(Relational DBMS): ๊ด€๊ณ„ํ˜• DBMS๋กœ Oracle, MySQL, MSSQL ๋“ฑ์ด ์žˆ๋‹ค.

2. MySQL ์„ค์น˜ํ•˜๊ธฐ

โ€ป ์šด์˜์ฒด์ œ์— ๋”ฐ๋ผ ์ฑ…์„ ์ฐธ๊ณ ํ•ด ์„ค์น˜

 

- MySQL ๋ช…๋ น ํ”„๋กฌํ”„ํŠธ๋กœ ์ ‘์†

์„ค์น˜๋œ ํด๋” ๊ฒฝ๋กœ๋กœ ์ด๋™ → (์ฝ˜์†”) mysql -h localhost -u root -p ์ž…๋ ฅ

3. ์›Œํฌ๋ฒค์น˜ ์„ค์น˜ํ•˜๊ธฐ

https://dev.mysql.com/downloads/workbench/

 

MySQL :: Download MySQL Workbench

 

dev.mysql.com

4. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ ํ…Œ์ด๋ธ” ์ƒ์„ฑํ•˜๊ธฐ

  1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒ์„ฑํ•˜๊ธฐ

MySQL ํ”„๋กฌํ”„ํŠธ์— ์ ‘์†ํ•ด ex) CREATE SCHEMA 'nodejs' DEFAULT CHARACTER SET utf8mb4 DEFA
ULT COLLATE utf8mb4_general_ci;  ์ž…๋ ฅ

- ํ•œ๊ธ€๊ณผ ์ด๋ชจํ‹ฐ์ฝ˜ ์‚ฌ์šฉ์„ ์œ„ํ•ด DEFAULT CHARACTER SET utf8mb4 DEFA
ULT COLLATE utf8mb4_general_ci

- SQL๊ตฌ๋ฌธ์„ ์ž…๋ ฅํ•œ ํ›„ ๋งˆ์ง€๋ง‰์— ์„ธ๋ฏธ์ฝœ๋ก (;) ๋ถ™์—ฌ์ฃผ๊ธฐ

- ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‚ฌ์šฉ: use [๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ช…];

 

    2. ํ…Œ์ด๋ธ” ์ƒ์„ฑํ•˜๊ธฐ

//์˜ˆ์‹œ - ์‚ฌ์šฉ์ž ํ…Œ์ด๋ธ”
CREATE TABLE nodejs.users (     
    -> id INT NOT NULL AUTO_INCREMENT,                          
    -> name VARCHAR(20) NOT NULL,                               
    -> age INT UNSIGNED NOT NULL,
    -> married TINYINT NOT NULL,  
    -> comment TEXT NULL,         
    -> created_at DATETIME NOT NULL DEFAULT now(),
    -> PRIMARY KEY(id),
    -> UNIQUE INDEX name_UNIQUE (name(ASC))
    -> COMMENT = '์‚ฌ์šฉ์ž ์ •๋ณด'
    -> ENGINE = InnoDB;

โ€ป์˜คํƒ€ ์ฃผ์˜

 

- ํ…Œ์ด๋ธ” ์ƒ์„ฑ: CREATE TABLE [๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ช….ํ…Œ์ด๋ธ”๋ช…];

- ์•„๋ž˜์— ํ•œ ์ค„์”ฉ ์ฝค๋งˆ๋กœ ๊ตฌ๋ถ„ํ•ด ์ปฌ๋Ÿผ(์„ธ๋กœ์ค„)์„ ๋งŒ๋“ ๋‹ค.

- ์ž๋ฃŒํ˜•: INT(์ •์ˆ˜ํ˜•), VARCHAR(์ž๋ฆฟ์ˆ˜), TINYINT, TEXT(๊ธด ๊ธ€ ์ €์žฅ ์‹œ), DATETIME(๋‚ ์งœ์™€ ์‹œ๊ฐ„) ๋“ฑ

- ์ปฌ๋Ÿผ ์„ค์ •: NOT NULL(๋นˆ์นธ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Œ), NULL(๋นˆ์นธ ํ—ˆ์šฉ), UNSIGNED(์Œ์ˆ˜ ๋ฌด์‹œ), AUTO_INCREMENT(์ˆซ์ž๋ฅผ ์ €์ ˆ๋กœ ์˜ฌ๋ฆผ), ZEROFILL(์ˆซ์ž์˜ ์ž๋ฆฟ์ˆ˜๊ฐ€ ๊ณ ์ „๋˜์–ด ์žˆ์„ ๋•Œ-๋น„์–ด์žˆ๋Š” ์ž๋ฆฌ์— ๋ชจ๋‘ 0), DEFAULT(๊ธฐ๋ณธ๊ฐ’), PRIMARY KEY(๊ธฐ๋ณธํ‚ค-๊ณ ์œ ํ•œ ์‹๋ณ„์ž), UNIQUE INDEX(ํ•ด๋‹น ๊ฐ’์ด ๊ณ ์œ ํ•ด์•ผ ํ•จ) ๋“ฑ์˜ ์˜ต์…˜

- ํ…Œ์ด๋ธ” ์ž์ฒด์— ๋Œ€ํ•œ ์„ค์ •: COMMENT(ํ…Œ์ด๋ธ” ๋ณด์ถฉ ์„ค๋ช…), ENGINE

 

- ํ…Œ์ด๋ธ” ํ™•์ธ ๋ช…๋ น: DESC [ํ…Œ์ด๋ธ”๋ช…];

- ํ…Œ์ด๋ธ” ์ œ๊ฑฐ ๋ช…๋ น: DROP TABLE [ํ…Œ์ด๋ธ”๋ช…];

 

- ๋‹ค๋ฅธ ํ…Œ์ด๋ธ”์˜ ๊ธฐ๋ณธํ‚ค๋ฅผ ์ €์žฅํ•˜๋Š” ์ปฌ๋Ÿผ: ์™ธ๋ž˜ํ‚ค(foreign key)

CONSTRAINT [์ œ์•ฝ์กฐ๊ฑด๋ช…] FOREIGN KEY [์ปฌ๋Ÿผ๋ช…] REFERENCES [์ฐธ๊ณ ํ•˜๋Š” ์ปฌ๋Ÿผ๋ช…]

- CASCADE: ์‚ฌ์šฉ์ž ์ •๋ณด๊ฐ€ ์ˆ˜์ •๋˜๊ฑฐ๋‚˜ ์‚ญ์ œ๋˜๋ฉด ๊ทธ๊ฒƒ๊ณผ ์—ฐ๊ฒฐ๋œ ๋Œ“๊ธ€ ์ •๋ณด๋„ ๊ฐ™์ด ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œ

- ํ…Œ์ด๋ธ” ํ™•์ธ: SHOW TABLES;

5. CRUD ์ž‘์—…ํ•˜๊ธฐ

  • CREATE(์ƒ์„ฑ)
    - ํ…Œ์ด๋ธ”์— ๋ฐ์ดํ„ฐ ๋„ฃ๊ธฐ
    INSERT INTO [ํ…Œ์ด๋ธ”๋ช…] ([์ปฌ๋Ÿผ1], [์ปฌ๋Ÿผ2], ..) VALUES ([๊ฐ’1], [๊ฐ’2],.. )
    ex) INSERT INTO nodejs.users (name, age, married, comment) VALUES ('hh', 24, 0, '์ž๊ธฐ์†Œ๊ฐœ1'); 
  • Read(์กฐํšŒ)
    - SELECT * FROM [ํ…Œ์ด๋ธ”๋ช…];
    * ๋Œ€์‹  ํŠน์ • ์ปฌ๋Ÿผ์„ ๋„ฃ์–ด ์กฐํšŒ ๊ฐ€๋Šฅ

    - WHERE ์ ˆ์„ ์‚ฌ์šฉํ•ด ํŠน์ • ์กฐ๊ฑด์„ ๊ฐ€์ง„ ๋ฐ์ดํ„ฐ ์กฐํšŒ ๊ฐ€๋Šฅ
    ex) select name, age from nodejs.users where married =1 and age>30;

    - ์ •๋ ฌ: ORDER BY [์ปฌ๋Ÿผ๋ช…] [ASC|DESC];
    ex) SELECT id, name FROM nodejs.users ORDER BY age DESC;
    - ์กฐํšŒํ•  ๋กœ์šฐ ๊ฐœ์ˆ˜ ์„ค์ • 'LIMIT [์ˆซ์ž]'๋ฅผ ๋์— ๋ถ™์—ฌ์ฃผ๊ธฐ
    - OFFSET [๊ฑด๋„ˆ๋›ธ ์ˆซ์ž]
  • Update(์ˆ˜์ •)
    - UPDATE [ํ…Œ์ด๋ธ”๋ช…] SET [์ปฌ๋Ÿผ๋ช…=๋ฐ”๊ฟ€ ๊ฐ’] WHERE [์กฐ๊ฑด];
    - ์กฐ๊ฑด AND, OR ์‚ฌ์šฉํ•ด์„œ ์—ฌ๋Ÿฌ ๊ฐœ ๊ฐ€๋Šฅ
  • Delete(์‚ญ์ œ)
    - DELETE FROM [ํ…Œ์ด๋ธ”๋ช…] WHERE [์กฐ๊ฑด];
    - ์กฐ๊ฑด AND, OR ์‚ฌ์šฉํ•ด์„œ ์—ฌ๋Ÿฌ ๊ฐœ ๊ฐ€๋Šฅ

โ€ป ์›Œํฌ๋ฒค์น˜ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ์ฑ… ์ฐธ๊ณ 

6. ์‹œํ€„๋ผ์ด์ฆˆ ์‚ฌ์šฉํ•˜๊ธฐ

์‹œํ€„๋ผ์ด์ฆˆ(Sequelize)

- MySQL ์ž‘์—…์„ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

- ORM(์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ฆด๋ ˆ์ด์…˜์„ ๋งคํ•‘ํ•ด ์ฃผ๋Š” ๋„๊ตฌ)์œผ๋กœ ๋ถ„๋ฅ˜

- ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ตฌ๋ฌธ์„ ์•Œ์•„์„œ SQL๋กœ ๋ฐ”๊ฟ”์ค€๋‹ค.

//์‹œํ€„๋ผ์ด์ฆˆ์— ํ•„์š”ํ•œ ํŒจํ‚ค์ง€ ์„ค์น˜
npm i express morgan numjucks sequelize sequelize-cli mysql2
npm i -D nodemon
//์„ค์น˜ ์™„๋ฃŒ ํ›„ 
npx sequelize init

์œ„์˜ ๋ช…๋ น์–ด ์‹คํ–‰ํ•˜๋ฉด config, models, migrations, seeders ํด๋” ์ƒ์„ฑ

 

โ‘  MySQL ์—ฐ๊ฒฐํ•˜๊ธฐ

- app.js ์ƒ์„ฑํ•˜๊ณ  ์ต์Šคํ”„๋ ˆ์Šค์™€ ์‹œํ€„๋ผ์ด์ฆˆ ์—ฐ๊ฒฐ ์ฝ”๋“œ ์ž‘์„ฑ

//apps.js
const express = require('express');
const path = require('path');
const morgan = require('morgan');
const nunjucks = require('nunjucks');

const { sequelize } = require('./models');
const indexRouter = require('./routes');
const usersRouter = require('./routes/users');
const commentsRouter = require('./routes/comments');

const app = express();
app.set('port', process.env.PORT || 3001);
app.set('view engine', 'html');
nunjucks.configure('views', {
  express: app,
  watch: true,
});
sequelize.sync({ force: false })
  .then(() => {
    console.log('๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์„ฑ๊ณต');
  })
  .catch((err) => {
    console.error(err);
  });

app.use(morgan('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/comments', commentsRouter);

app.use((req, res, next) => {
  const error =  new Error(`${req.method} ${req.url} ๋ผ์šฐํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.`);
  error.status = 404;
  next(error);
});

app.use((err, req, res, next) => {
  res.locals.message = err.message;
  res.locals.error = process.env.NODE_ENV !== 'production' ? err : {};
  res.status(err.status || 500);
  res.render('error');
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '๋ฒˆ ํฌํŠธ์—์„œ ๋Œ€๊ธฐ ์ค‘');
});
//config/config.json-> ๊ฐœ์ธ์˜ ์„ค์ •์— ๋งž๊ฒŒ ์ˆ˜์ •
{
  "development": {
    "username": "root",
    "password": "[password]",
    "database": "nodejs",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },

์œ„์˜ ๋‘ ์ฝ”๋“œ ์ˆ˜์ • ํ›„ (ํ”„๋กฌํ”„ํŠธ)npm start๋กœ ์„œ๋ฒ„ ์‹คํ–‰ํ•˜๋ฉด 3001 ํฌํŠธ์—์„œ ์„œ๋ฒ„๊ฐ€ ๋Œ์•„๊ฐ„๋‹ค.

 

โ‘ก ๋ชจ๋ธ ์ •์˜ํ•˜๊ธฐ

MySQL์—์„œ ์ •์˜ํ•œ ํ…Œ์ด๋ธ”์„ ์‹œํ€„๋ผ์ด์ฆˆ์—์„œ๋„ ์ •์˜ํ•ด์•ผ ํ•œ๋‹ค.

//models/user.js
const Sequelize = require('sequelize');

class User extends Sequelize.Model {
  static initiate(sequelize) {
    User.init({
      name: {
        type: Sequelize.STRING(20),
        allowNull: false,
        unique: true,
      },
      age: {
        type: Sequelize.INTEGER.UNSIGNED,
        allowNull: false,
      },
      married: {
        type: Sequelize.BOOLEAN,
        allowNull: false,
      },
      comment: {
        type: Sequelize.TEXT,
        allowNull: true,
      },
      created_at: {
        type: Sequelize.DATE,
        allowNull: false,
        defaultValue: Sequelize.NOW,
      },
    }, {
      sequelize,
      timestamps: false,
      underscored: false,
      modelName: 'User',
      tableName: 'users',
      paranoid: false,
      charset: 'utf8',
      collate: 'utf8_general_ci',
    });
  }

  static associate(db) {
    db.User.hasMany(db.Comment, { foreignKey: 'commenter', sourceKey: 'id' });
  }
};

module.exports = User;

์ž๋ฃŒํ˜•, ์˜ต์…˜ ๋“ฑ์˜ ํ˜•ํƒœ๊ฐ€ ๋‹ค๋ฅด๋‹ค. 

- ๋ชจ๋ธ.init ๋ฉ”์„œ๋“œ์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋Š” ํ…Œ์ด๋ธ” ์˜ต์…˜์ด๋‹ค.

- sequelize: db.sequelize ๊ฐ์ฒด๋ฅผ ๋„ฃ์–ด์•ผ ํ•œ๋‹ค, static initiate ๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์—ฐ๊ฒฐ

- timestamps, underscored, modelName, tableName, paranoid, charset๊ณผ collate(ํ•œ๊ธ€๋กœ ์„ค์ •) ๋“ฑ

+ Comment ๋ชจ๋ธ๋„ ๋งŒ๋“ค๊ณ  models/index.js์™€ ์—ฐ๊ฒฐํ•˜๊ธฐ

//models/index.js
const Sequelize = require('sequelize');
const User = require('./user');
const Comment = require('./comment');

const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const db = {};

const sequelize = new Sequelize(config.database, config.username, config.password, config);

db.sequelize = sequelize;

db.User = User;
db.Comment = Comment;

User.initiate(sequelize);	//๊ฐ๊ฐ์˜ ๋ชจ๋ธ์˜ static initiate ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ
Comment.initiate(sequelize);

User.associate(db);
Comment.associate(db);

module.exports = db;

 db ๊ฐ์ฒด์— User์™€ Comment ๋ชจ๋ธ์ด ๋‹ด๊ฒจ์žˆ๋‹ค. (์ฆ‰, db ๊ฐ์ฒด๋ฅผ require ํ•ด์„œ User์™€ Comment ๋ชจ๋ธ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.)

 

โ‘ข ๊ด€๊ณ„ ์ •์˜ํ•˜๊ธฐ

- ์ผ๋Œ€๋‹ค, ์ผ๋Œ€์ผ, ๋‹ค๋Œ€๋‹ค ๊ด€๊ณ„๊ฐ€ ์žˆ๋‹ค.

- 1:N

require ๋ฐฉ์‹(์ˆœํ™˜ ์ฐธ์กฐ)์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด index.js์—์„œ ๊ฐ ๋ชจ๋ธ์„ ๋ถˆ๋Ÿฌ์™€ db ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋„˜๊ธฐ๋Š” ๋ฐฉ์‹์„ ์ทจํ•œ๋‹ค.

๋‹ค๋ฅธ ๋ชจ๋ธ์˜ ์ •๋ณด๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” ํ…Œ์ด๋ธ”์—๋Š” belongsTo ์‚ฌ์šฉ

hasMany ๋ฉ”์„œ๋“œ์—์„œ๋Š” source ์†์„ฑ์— id, belongsTo ๋ฉ”์„œ๋“œ์—์„œ๋Š” targetKey ์†์„ฑ์— id๋ฅผ ๋„ฃ๋Š”๋‹ค.

- foreignKey๋ฅผ ๋”ฐ๋กœ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด '๋ชจ๋ธ๋ช…+๊ธฐ๋ณธ ํ‚ค'์ธ ์ปฌ๋Ÿผ์ด ๋ชจ๋ธ์— ์ƒ์„ฑ๋œ๋‹ค.

- npm start ๋ช…๋ น์–ด๋กœ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์Šค์Šค๋กœ SQL๋ฌธ์„ ์‹คํ–‰ํ•œ๋‹ค.

 

- 1:1

- hasOne ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ

ex) db.User.hasOne(db.Info, { foreignKey: 'UserId', sourceKey: 'id' });

 

- N:M

- belongsToMany ๋ฉ”์„œ๋“œ ์‚ฌ์šฉํ•œ๋‹ค.(์–‘์ชฝ ๋ชจ๋ธ ๋ชจ๋‘์—)

- ์ƒˆ๋กœ์šด ๋ชจ๋ธ์ด ์ƒ์„ฑ๋œ๋‹ค.

 ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ ๋ชจ๋ธ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด db.sequelize.models.PostHashtag

 

โ‘ฃ ์ฟผ๋ฆฌ ์•Œ์•„๋ณด๊ธฐ

- ์ฟผ๋ฆฌ๋Š” ํ”„๋กœ๋ฏธ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ then์„ ๋ถ™์—ฌ ๊ฒฐ๊ด๊ฐ’์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. 

- models ๋ชจ๋“ˆ์—์„œ User ๋ชจ๋ธ์„ ๋ถˆ๋Ÿฌ์™€ create ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

โ€ป MySQL ์ž๋ฃŒํ˜•์ด ์•„๋‹Œ ์‹œํ€„๋ผ์ด์ฆˆ ๋ชจ๋ธ์— ์ •์˜ํ•œ ์ž๋ฃŒํ˜•๋Œ€๋กœ ๋„ฃ์–ด์•ผ ํ•œ๋‹ค. (๋ถ€ํ•ฉํ•˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์—ˆ์„ ๋•Œ ์—๋Ÿฌ ๋ฐœ์ƒ)

- ๋ชจ๋“  ๋ฐ์ดํ„ฐ ์กฐํšŒ๋Š” findAll ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ

- attributes ์˜ต์…˜(์›ํ•˜๋Š” ์นผ๋Ÿผ๋งŒ) , where ์˜ต์…˜(์กฐ๊ฑด), order ์˜ต์…˜(์ •๋ ฌ), limit ์˜ต์…˜(๊ฐœ์ˆ˜ ์„ค์ •), offset ์†์„ฑ, update ๋ฉ”์„œ๋“œ, destroy ๋ฉ”์„œ๋“œ(๋กœ์šฐ ์‚ญ์ œ)

- 0p ๊ฐ์ฒด: 0p . gt(์ดˆ๊ณผ), 0p . or(๋˜๋Š”) ๋“ฑ

 

  • ๊ด€๊ณ„ ์ฟผ๋ฆฌ

- (ํ˜„์žฌ User ๋ชจ๋ธ)

- ํŠน์ • ์‚ฌ์šฉ์ž๋ฅผ ๊ฐ€์ ธ์˜ค๋ฉด์„œ ๊ทธ ์‚ฌ๋žŒ์˜ ๋Œ“๊ธ€๊นŒ์ง€ ๊ฐ€์ ธ์˜ค๊ณ  ์‹ถ๋‹ค๋ฉด include ์†์„ฑ(include ๋ฐฐ์—ด์— ๋„ฃ์–ด์ค€๋‹ค)์„ ์‚ฌ์šฉํ•œ๋‹ค.

- ๊ด€๊ณ„ ์„ค์ • ํ›„ getComments(์กฐํšŒ), setComments(์ˆ˜์ •), addComment(ํ•˜๋‚˜ ์ƒ์„ฑ), addComments(์—ฌ๋Ÿฌ ๊ฐœ ์ƒ์„ฑ), removeComments(์‚ญ์ œ) ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉ๊ฐ€๋Šฅํ•˜๋‹ค.

- ๋ชจ๋ธ์˜ ์ด๋ฆ„ ๋ฐ”๊พธ๋ ค๋ฉด as ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

- where, attributes ์˜ต์…˜ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

 ์ฟผ๋ฆฌ ์กฐํšŒ

- ์ถ”๊ฐ€๋Š” ์•„์ด๋””๋ฅผ ์ด์šฉํ•ด ๋ฐฐ์—ด๋กœ ๊ฐ€๋Šฅํ•˜๋‹ค. ์ˆ˜์ •, ์‚ญ์ œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€

  • SQL ์ฟผ๋ฆฌํ•˜๊ธฐ

- SQL๋ฌธ์„ ํ†ตํ•ด ์ฟผ๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

โ‘ค ์ฟผ๋ฆฌ ์•Œ์•„๋ณด๊ธฐ

- (๋ชจ๋ธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ ํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋ง ํ•œ๋‹ค, JSON ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.) ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹์ด ์žˆ๋‹ค.

- views/sequelize.html, error.html

- public/sequelize.js  --- script ํƒœ๊ทธ์— ๋ฒ„ํŠผ์ด ๋ˆŒ๋ ธ์„ ๋•Œ ์„œ๋ฒ„์˜ ๋ผ์šฐํ„ฐ๋กœ AJAX ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์ฝ”๋“œ ๋“ค์–ด์žˆ๋‹ค.

- app.js 

ํŒŒ์ผ๋“ค์„ ๋งŒ๋“ ๋‹ค.

//routes/index.js

const express = require('express');
const User = require('../models/user');

const router = express.Router();

router.get('/', async (req, res, next) => {
  try {
    const users = await User.findAll();
    res.render('sequelize', { users });
  } catch (err) {
    console.error(err);
    next(err);
  }
});

module.exports = router;

(๋ชจ๋ธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ ํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋ง) User.findAll ๋ฉ”์„œ๋“œ๋กœ ๋ชจ๋“  ์‚ฌ์šฉ์ž๋ฅผ ์ฐพ๊ณ , ๊ฒฐ๊ด๊ฐ’์ธ users๋ฅผ ๋„ฃ๋Š”๋‹ค.

- ์‹œํ€„๋ผ์ด์ฆˆ๋Š” ํ”„๋กœ๋ฏธ์Šค๋ฅผ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— async/await ์™€ try/catch๋ฌธ์„ ์‚ฌ์šฉํ•ด์„œ ์„ฑ๊ณต๊ณผ ์‹คํŒจ ์‹œ์˜ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

//routes/users.js
const express = require('express');
const User = require('../models/user');
const Comment = require('../models/comment');

const router = express.Router();

router.route('/')
  .get(async (req, res, next) => {
    try {
      const users = await User.findAll();
      res.json(users);
    } catch (err) {
      console.error(err);
      next(err);
    }
  })
  .post(async (req, res, next) => {
    try {
      const user = await User.create({
        name: req.body.name,
        age: req.body.age,
        married: req.body.married,
      });
      console.log(user);
      res.status(201).json(user);
    } catch (err) {
      console.error(err);
      next(err);
    }
  });

router.get('/:id/comments', async (req, res, next) => {
  try {
    const comments = await Comment.findAll({
      include: {
        model: User,
        where: { id: req.params.id },
      },
    });
    console.log(comments);
    res.json(comments);
  } catch (err) {
    console.error(err);
    next(err);
  }
});

module.exports = router;

(JSON ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค) ์‚ฌ์šฉ์ž๋ฅผ ์กฐํšŒํ•˜๋Š” ์š”์ฒญ๊ณผ (GET /users) ๋“ฑ๋กํ•˜๋Š” ์š”์ฒญ (POST /users)๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค.

- where, include ์˜ต์…˜ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

- routes/comments.js ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•ด ๋Œ“๊ธ€๊ณผ ๊ด€๋ จ๋œ CRUD ์ž‘์—…์„ ํ•œ๋‹ค.

- ํŒŒ์ผ์„ ๋ชจ๋‘ ์ƒ์„ฑ ํ›„ npm start๋กœ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.  http://localhost:3001 ๋กœ ์ ‘์†ํ•ด ํ™•์ธํ•œ๋‹ค.

httP://localhost:3001 ์‹คํ–‰์‹œ ํ™”๋ฉด


Quiz

1. ๊ด€๋ จ์„ฑ์„ ๊ฐ€์ง€๋ฉฐ ์ค‘๋ณต์ด ์—†๋Š” ๋ฐ์ดํ„ฐ๋“ค์˜ ์ง‘ํ•ฉ์„ (      )๋ผ ํ•œ๋‹ค.

2. ๋งŒ๋“ค์–ด์ง„ users ํ…Œ์ด๋ธ”์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ ๋ช…๋ น์–ด๋Š” (          )์ด๋‹ค.

3. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ์ƒ์„ฑ, ์กฐํšŒ, ์ˆ˜์ •, ์‚ญ์ œ 4๊ฐ€์ง€ ์ž‘์—…์„ (    )๋ผ๊ณ  ํ•œ๋‹ค. 

4. ์„œ๋ฒ„ ์‹คํ–‰ ๋ช…๋ น์–ด๋Š” (         )์ด๋‹ค.

5. MySQL ์ž‘์—…์„ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ตฌ๋ฌธ์„ ์Šค์Šค๋กœ SQL๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ๊ฒƒ์„ (     )๋ผ๊ณ  ํ•œ๋‹ค. 

6. ์‹œํ€„๋ผ์ด์ฆˆ์—์„œ hasMany๋ฉ”์„œ๋“œ๋กœ ํ‘œํ˜„ํ•˜๋Š” ๊ด€๊ณ„๋Š” (   )์ด๋‹ค.

7. ์ฟผ๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ๋•Œ ๋ชจ๋ธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ ํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋ง ํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ (    ) ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ• ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

Programming Quiz

8. ์•„๋ž˜์˜ ํ…Œ์ด๋ธ”(users)์— 2๊ฐœ์˜ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ์„ ์œ„ํ•œ ๋ช…๋ น์–ด๋ฅผ ์ž‘์„ฑํ•˜์‹œ์˜ค.

 

9. ๋ผ์šฐํ„ฐ๋ฅผ ๋งŒ๋“œ๋Š” ํŒŒ์ผ์ด๋‹ค. ๋นˆ์นธ์„ ์ฑ„์šฐ์‹œ์˜ค.

//routes/index.js
const express = require('express');
const User = require('../models/user');

const router = express.Router();

router.get('/', async (req, res, next) => {
  try {
    const users = await User.(1.     )();	//๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด ๋ชจ๋“  ์‚ฌ์šฉ์ž ์ฐพ๊ธฐ
    res.render('sequelize', { (2.    ) });	//sequelize.html์„ ๋ Œ๋”๋งํ•  ๋•Œ ๊ฒฐ๊ณผ ๊ฐ’
  } catch (err) {
    console.error(err);
    next(err);
  }
});

module.exports = (3     );	//๋‹ค๋ฅธ ํŒŒ์ผ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋‚ด๋ณด๋ƒ„

Answer

1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค

2. DESC users;

3. CRUD

4. npm start

5. ์‹œํ€„๋ผ์ด์ฆˆ

6. 1:N

7. JSON

8.

mysql(ํ”„๋กฌํ”„ํŠธ)> INSERT INTO nodejs.users (name, age, married, comment) VALUES ('hh', 21, 0, '์ž๊ธฐ์†Œ๊ฐœ1');

mysql(ํ”„๋กฌํ”„ํŠธ)> INSERT INTO nodejs.users (name, age, married, comment) VALUES ('dd', 25, 0, '์ž๊ธฐ์†Œ๊ฐœ12');

 

9.

//routes/index.js
const express = require('express');
const User = require('../models/user');

const router = express.Router();

router.get('/', async (req, res, next) => {
  try {
    const users = await User.(1. findAll )();	
    res.render('sequelize', { (2. users ) });	
  } catch (err) {
    console.error(err);
    next(err);
  }
});

module.exports = (3. router );

 

์ถœ์ฒ˜) ์กฐํ˜„์ •, ใ€ŒNode.js ๊ต๊ณผ์„œ ๊ฐœ์ • 3ํŒใ€, ๊ธธ๋ฒ—(2022), 6์žฅ

 

Corner node.js 2ํŒ€

Editor : Igumi

728x90

๊ด€๋ จ๊ธ€ ๋”๋ณด๊ธฐ