[ORM] ๐ sequelize-cli ๋ชจ๋ ์ฌ์ฉํ๊ธฐ
sequelize-cli ๋ชจ๋
[sequelize-cli]
- ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๊ตฌ์ถ๋์ง์๋๋ผ๋, ํ๋ก์ ํธ๋ง ๋ฐ์์ ์ค์ ํ๊ณ ์๋ฒ์คํ๋ง ํ๋ฉด ์์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ ์์ฑํด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
- ๋๊ตฐ๊ฐ์ ํ๋ก์ ํธ๋ฅผ ๋ฐ์์ ๋น ๋ฅด๊ฒ wasํ๊ฒฝ์ ๋๋ฆด์ํฉ์ด๋ฉด ์ข์ ์ ํ์ง๋ค.
- ๋ชจ๋ธ ์ฝ๋ ์์ฑ → ์๋ create๋ฌธ ๋ณํ → RDB ํ ์ด๋ธ ์์ฑ
[sequelize-auto]
- ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ด๋ฏธ ๊ตฌ์ถํ ์ํ๋ผ๋ฉด, ์ธ๋ชจ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค.
- ์ด๋ฏธ ๊ตฌ์ถ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง๋ฅผ ๋ฐํ์ผ๋ก orm ๋ชจ๋ธ์ ์๋์ผ๋ก ์์ฑํด์ค๋ค.
- ํ๋ค๊ฒ sql์ง๊ณ orm์ฝ๋ฉ ํ๋ ๋๋ฒ์ ๋ฒ๊ฑฐ๋ก์์ ์์ ์ค๋ค.
- ์ด๋ฏธ ์ง์ฌ์ง ํ ์ด๋ธ์ ๊ธฐ๋ฐ์ผ๋ก → ์๋์ผ๋ก ๋ชจ๋ธ ์ฝ๋ ์์ฑ
sequelize-cli ์ฌ์ฉ ์ค์
> npm i sequelize sequelize-cli mysql2
sequelize-cli
The Sequelize CLI. Latest version: 6.4.1, last published: 3 months ago. Start using sequelize-cli in your project by running `npm i sequelize-cli`. There are 422 other projects in the npm registry using sequelize-cli.
www.npmjs.com
sequelize-cli - ์ด๊ธฐ ์ค์
> npx sequelize init
sequelize init ์ ํ๊ฒ๋๋ฉด, ๋ช๊ฐ์ง ํด๋์, ํ์ผ๋ค์ด ์์ฑ๋๋ค.
config.json
- DB ์ฐ๊ฒฐ ์ ๋ณด๋ฅผ ์ ์ฅ
{
"development": {
"username": "test",
"password": "123123",
"database": "nodebird",
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "test",
"password": "123123",
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "test",
"password": "123123",
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
sequelize-cli - ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ฑ
> npx sequelize db:create
db:create CLI ๋ช ๋ น์ ํ์ฉํ๊ฒ ๋๋ฉด DB์คํค๋ง๋ฅผ mysql์์ ์์ฑํ์ง ์๋๋ผ๋ ๋ช ๋ น์ด ํ์ค๋ก ์์ฑํด์ค ์ ์๋ค.
config.json์์ ์ค์ ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ด๋ฆ "nordbird"๊ฐ ์คํค๋ง์ ์๋์ผ๋ก ์ ์ถ๊ฐ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
sequelize-cli - ํ ์ด๋ธ ์์ฑ
ํ ์ด๋ธ์ ์ฐ๊ฒฐํ ๋ชจ๋ธ์ ์์ฑํ๋ค.
user.js
const Sequelize = require('sequelize');
module.exports = class User extends Sequelize.Model {
static init(sequelize) {
return super.init(
{
// ์ํ๋ผ์ด์ฆ๋ id ์๋ ์์ฑ (auto_increament)
email: {
type: Sequelize.STRING(40),
allowNull: true, // null ํ์ฉ
unique: true, // ์ค๋ณต ๋นํ์ฉ
},
nick: {
type: Sequelize.STRING(15),
allowNull: false,
},
password: {
type: Sequelize.STRING(100), // ํด์์ํธํ๋ฅผ ํ ๋ ๋ฌธ์๊ฐ ๊ธธ์ด์ง๋, ์ฌ์ ์๊ฒ ์ฉ๋์ ์ก์์ค๋ค.
allowNull: true, // ์นด์นด์ค ๊ฐ์ api๋ก ๋ก๊ทธ์ธํ ๋, ์ง์ ํ์๊ฐ์
ํด์ ๋น๋ฐ๋ฒํธ ์ค์ ํ๊ฒ ์๋๋ ๋น๋ฒ์ null์ผ์๋ ์๋ค.
},
provider: {
//? ์ด๋๋ก๋ถํฐ ๋ก๊ทธ์ธ ํ๋์ง ์ ๋ณด
type: Sequelize.STRING(10),
allowNull: false,
defaultValue: 'local', // ๋ก์ปฌ / ์นด์นด์ค / ๋ค์ด๋ฒ / ๊ตฌ๊ธ ๋ก๊ทธ์ธ ์ ๊ตฌ๋ถํ๊ธฐ ์ํ ํ๋
},
snsId: {
//? sns์ผ๋ก ๋ก๊ทธ์ธํ ๊ฒฝ์ฐ sns์์ด๋ ์ ์ฅ ํ๋
type: Sequelize.STRING(30),
allowNull: true,
},
},
{
sequelize,
timestamps: true, // createdAt, udaptedAt ์๋ ์์ฑ
underscored: false,
modelName: 'User', // ๋ชจ๋ธ๋ช
tableName: 'users', // ํ
์ด๋ธ๋ช
paranoid: true, // deletedAt ์๋ ์์ฑ
charset: 'utf8', // ํ๊ธ ์
๋ ฅ ์ค์
collate: 'utf8_general_ci',
},
);
}
static associate(db) {
/*
* ๋ฐ๋ก ์ธ๋ํค๋ฅผ ์ง์ ํ์ง์์ผ๋ฉด, ๋ชจ๋ธ๋ช
+๊ธฐ๋ณธํค ์ปฌ๋ผ์ด ์์ฑ๋์ ์๋์ผ๋ก ์ฐ๊ฒฐ๋๋ค.
* ์ฆ, User์ id๊ฐ ํฉ์ณ์ ธ์ Userid๋ผ๋ ํ๋๊ฐ ์๊ฒจ์ ์๋์ฐ๊ฒฐํด์ค๋ค.
* db.User.hasMany(db.Post, { foreignKey: 'Userid', targetKey: 'id' })
*/
db.User.hasMany(db.Post);
/*
* ํ๋ก์ ์ ํ๋ก์ ๊ด๊ณ
* ์ ์๊ฐํด๋ณด์. ํ๋ก์,ํ๋ก์ ์ ๋ณด๋ ๋ชจ๋ User๋ชจ๋ธ์์ ๊ฐ์ ธ์ค๋ ์ ๋ณด๋ค์ด๋ค. ๋ฐ๋ผ์ ์๊ธฐ์์ ์ ์ฐธ์กฐํ๋ ๊ด๊ณ๊ฐ ์๊ฒจ๋๋ค.
* Follow๋ผ๋ ์ค๊ฐํ
์ด๋ธ์ ๋ง๋ค์ด์ M:N๊ด๊ณ๋ฅผ ํ์ฑํ๋ค.
*/
db.User.belongsToMany(db.User, {
foreignKey: 'followingId', // ํ๋ก์ ๋นํ ์ฌ๋. ์ฃผ์ฒด (์ฆ, ์ ๋ช
ํ ์ฌ๋. ์ฐ์์ธ, ์ ํ๋ฒ)
as: 'Followers', // ๋ชจ๋ธ์ฟผ๋ฆฌ์์ ์ฌ์ฉ๋ ํ๋ ๋ณ๋ช
. sql๋ฌธ์ ํ๋๋ช
as ๋ณ๋ช
๊ณผ ๊ฐ๋ค.
through: 'Follow',
});
db.User.belongsToMany(db.User, {
foreignKey: 'followerId', // ๊ทธ ์ฌ๋์ ํ๋ก์ ํ ์ฌ๋๋ค
as: 'Followings',
through: 'Follow',
});
}
};
followerId (ํ๋ก์๋ฅผ ํ ์ฌ๋) | followingId (ํ๋ก์ ๋นํ ์ฌ๋. ์ฃผ์ฒด.) (์ฆ, ์ ๋ช ํ ์ฌ๋. ์ฐ์์ธ, ์ ํ๋ฒ) |
1 | 3 |
4 | 3 |
5 | 3 |
2 | 1 |
1 | 2 |
4 | 1 |
- id๊ฐ 3์ธ ์ฌ๋์ id๊ฐ 1,4,5์ธ ์ฌ๋์๊ฒ ํ๋ก์ ๋นํ๋ค. ์ฆ, id๊ฐ 3์ธ ์ฌ๋์ ํ๋ก์ ์๊ฐ 3๋ช .
- id๊ฐ 1์ธ ์ฌ๋์ id๊ฐ 3๊ณผ 2์ธ ์ฌ๋์ ํ๋ก์ฐ ํ๊ณ ์๋ค. ์ฆ id๊ฐ 1์ธ ์ฌ๋์ด ํ๋ก์ฐ ํ ์ ํ๋ฒ๊ฐ 2๋ช
ํ๋ก์ฐ
์น๊ตฌ๋ฅผ ๋ง๋๋ ํ์. ์ธ์คํ์์ ํ๋ก์ฐ๋ฅผ ํ๋ฉด ์น์ถ ์ถ๊ฐ๋ฅผ ์๋ฏธ.
ํ๋ก์
์๋๋ฐฉ์ด ๋๋ฅผ ๋จผ์ ํ๋ก์ฐ ํ๊ฒ๋๋ฉด ํ๋ก์์ ์ซ์๊ฐ ์ฆ๊ฐํ๋ค. ์ฆ ๋๋ฅผ ์น๊ตฌ๋ก ์ถ๊ฐํ ์ฌ๋์ด๋ ์๋ฏธ์ด๋ค.
ํ๋ก์
๋ด๊ฐ ๋จผ์ ์๋๋ฐฉ์ ํ๋ก์ฐ ํ๊ฒ ๋๋ฉด ํ๋ก์์ ์ซ์๊ฐ ์ฆ๊ฐํ๋ค. ์ฆ ๋ด๊ฐ ์น๊ตฌ๋ก ์ถ๊ฐํ ์ฌ๋์ด๋ ์๋ฏธ์ด๋ค.
post.js
const Sequelize = require('sequelize');
module.exports = class Post extends Sequelize.Model {
static init(sequelize) {
return super.init(
{
content: {
type: Sequelize.STRING(140),
allowNull: false,
},
img: {
type: Sequelize.STRING(200),
allowNull: true,
},
},
{
sequelize,
timestamps: true,
underscored: false,
modelName: 'Post',
tableName: 'posts',
paranoid: false, // ๊ฒ์๊ธ ์ญ์ ํ๋ฉด, ํด์งํต ์๊ฑฐ์น๊ณ ์นผ์ญ์
charset: 'utf8mb4', // ์ด๋ชจํฐ์ฝ ๊ฐ๋ฅ ์ค์
collate: 'utf8mb4_general_ci',
},
);
}
static associate(db) {
db.Post.belongsTo(db.User);
db.Post.belongsToMany(db.Hashtag, { through: 'PostHashtag' });
}
};
hashtag.js
const Sequelize = require('sequelize');
module.exports = class Hashtag extends Sequelize.Model {
static init(sequelize) {
return super.init(
{
title: {
type: Sequelize.STRING(15),
allowNull: false,
unique: true,
},
},
{
sequelize,
timestamps: true,
underscored: false,
modelName: 'Hashtag',
tableName: 'hashtags',
paranoid: false,
charset: 'utf8mb4',
collate: 'utf8mb4_general_ci',
},
);
}
static associate(db) {
db.Hashtag.belongsToMany(db.Post, { through: 'PostHashtag' });
}
};
index.js : ๋ชจ๋ธ
- ํ ์ด๋ธ ์ฐ๊ฒฐ์ ์
const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
//? ๋ชจ๋ธ ๋ชจ๋
const User = require('./user');
const Post = require('./post');
const Hashtag = require('./hashtag');
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
//? db๊ฐ์ฒด์ ๋ชจ๋ธ ์ ๋ณด๋ค ๋ฃ์
db.sequelize = sequelize;
db.User = User;
db.Post = Post;
db.Hashtag = Hashtag;
//? ๋ชจ๋ธ - ํ
์ด๋ธ ์ฐ๊ฒฐ
User.init(sequelize);
Post.init(sequelize);
Hashtag.init(sequelize);
//? ๋ชจ๋ธ ๊ด๊ณ ์ค์
User.associate(db);
Post.associate(db);
Hashtag.associate(db);
module.exports = db;
sequelize-cli - ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ
๋ชจ๋ธ์ ์ค์ ํด์คฌ์ผ๋ฉด, ์๋ฒ๋ฅผ ์คํ ์์ผ ์ฐ๊ฒฐํ๋๋ก ํ์.
app.js
//* DB ์ฐ๊ฒฐ ๋ฐ ์์ฑ
sequelize
.sync({ force: false })
.then(() => {
console.log('๋ฐ์ดํฐ ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์ฑ๊ณต');
})
.catch(err => {
console.error(err);
});
[sequelize.sync ์ต์ ]
- force: true
- ๋ชจ๋ธ์ ์์ ํ๋ฉด, ์ด๋ฅผ db์ ๋ฐ์ํ๊ธฐ ์ํ ์ต์ ์ด๋ค.
- ๋จ, ํ
์ด๋ธ์ ์ง์ ๋ค ๋ค์ ์์ฑํ๋ ๊ฑฐ๋ผ์ ๊ธฐ์กด ๋ฐ์ดํฐ๊ฐ ๋ ์๊ฐ๋ค.
- alter: true
- ๊ธฐ์กด ๋ฐ์ดํฐ๋ฅผ ์ ์งํ๋ฉด์ ํ ์ด๋ธ์ ์ ๋ฐ์ดํธ ํ ์์๋ค.
- ๋ค๋ง, ํ๋๋ฅผ ์๋ก ์ถ๊ฐํ ๋ ํ๋๊ฐ notnull์ด๋ฉด ์ ์ฝ์กฐ๊ฑด์ ๋ฐ๋ผ ์ค๋ฅ๊ฐ ๋๋ ๋ฑ ๋์ฒ๋ฅผ ํด์ผ ํ๋ค.
- ๊ทธ๋ฅ ์ํฌ๋ฒค์น ๋ค์ด๊ฐ์ ์ง์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ชจ๋ธ์ ๋ ธ๊ฐ๋ค๋ผ๋ ์์ ํ๋๊ฒ์ด ๋ ์์ ํ๋ค.
- ์ด๋ฌํ ์ต์ ์ ์ด๋๊น์ง๋ developmentํ๊ฒฝ์ผ๋๋ง ์ ์ฉํ๋ค.
์๋ฒ๋ฅผ ์คํ ์ํค๊ณ mysql์ํฌ๋ฒค์น์ ๋ค์ด๊ฐ์ ํ์ธํด๋ณด๋ฉด, ํ ์ด๋ธ์ด ์์ฑ๋์ด์๊ณ , ์ธ๋ํค ๊ด๊ณ๋ ์ ์ค์ ๋จ์ ํ์ธ ํ ์ ์๋ค.
๋ค์์ ์์ฑํ ํ ์ด๋ธ์ ERD ์ด๋ค.