이 글은 Getting Started with Sequelize and Postgres를 참고해서 작성하였습니다.
- ORM(Object Relational Mapping)은 SQL 대신에 데이터베이스와 소통할 수 있게 해주는 프로그래밍 언어입니다. 즉 SQL 대신에 코드로 쿼리문을 작성할 수 있게 해줍니다.
npm install sequelize sequelize-cli pg pg-hstore dotenv
혹은
yarn add sequelize sequelize-cli pg pg-hstore dotenv
을 입력해서 dependency들을 설치해주세요
sequelize
는 sequelize 라이브러리 사용 및 PostgreSQL DB서버와 연결하게 해줌sequelize-cli
는 sequelize 관련 명령어로 데이터베이스 작업을 해주는 툴새로 .sequelizerc
라는 파일을 만들고 다음과 같이 코드를 작성합니다.
const path = require('path')
module.exports = {
'config': path.resolve('./database/config', 'config.js'),
'models-path': path.resolve('./database/models'),
'migrations-path': path.resolve('./database/migrations'),
'seeders-path': path.resolve('./database/seeders')
}
'config'
: PostgreDB 서버와 연결할 connection string를 설정하는 폴더를 sequelize-cli가 생성하도록 해줌
'models-path'
: 테이블의 스키마를 정의해준 디렉토리. sequelize-cli
가 이 파일을 바탕으로 마이그레이션 파일을 생성.
'migrations-path'
: 실제로 cli가 DB서버에 테이블을 만들도록 도와주는 디렉토리.
'seeders-path'
: 실제 데이터들을 넣는 폴더. cli가 데이터들을 보고 DB의 테이블에 데이터들을 넣음.
다음 명령어를 실행합니다.
npx sequelize init
./node_modules/.bin/sequelize
쓰는 대신에 npx가./node_modules/.bin
을 가리키게 해줍니다.
./node_modules/.bin/sequelize
를 실행해야 하는 이유는 sequelize-cli가 global하게 설치 하지 않고 로컬에 설치했기 때문입니다. Global하게 설치하면sequelize init
으로 실행시킬 있습니다. Sequelize CLI를 사용하여 User API 만들기 참고
그러면 위의 사진 같이 `./database/` 디렉토리 안에 `config`, `models`, `migrations`, `seeders` 폴더가 생성됩니다.
database/config/
안에 config.js
를 밑의 코드로 대체해줍니다
require('dotenv').config()
module.exports = {
development: {
url: process.env.DEV_DATABASE_URL,
dialect: 'postgres',
},
test: {
url: process.env.TEST_DATABASE_URL,
dialect: 'postgres',
},
production: {
url: process.env.DATABASE_URL,
dialect: 'postgres',
},
}
방법 1) pgAdmin에 들어가서 왼쪽에 Servers-PostgreSQL 12-Databases
에 마우스 우클릭 하고 my_db
라는 이름으로 Database를 만듭니다
방법 2) cli를 이용해서 Database를 만듭니다. Database를 만들기 위해 아래의 명령어를 입력합니다.
npx createdb my_db -U <db_user>
<db_user>는 Datases의 properties에서 볼 수 있습니다.
npm install dotenv
혹은 yarn add dotenv
를 입력하여 dotenv
를 설치하고 .dotenv
파일을 생성하여 아래와 같이 입력합니다.
DEV_DATABASE_URL=postgres://<db_user>:<db_password>@127.0.0.1:5432/my_db
방법2 에서 <db_user>가 어떤 것인지 확인해주세요
예를 들어 레딧 같은 커뮤니티 웹사이트를 만들어 본다고 가정해봅시다. 우리는 User, Post, Comment라는 테이블이 필요합니다. 그러면 다음과 같은 관계가 생깁니다.
- User는 여러개의 Post를 가집니다. (One To Many)
- User는 여러개의 Comment를 가집니다. (One To Many)
- Post는 여러개의 Comment를 가집니다. (One To Many)
이러한 테이블 관계를 만들기 위해 계속해서 봅시다.
sequelize-cli로 User, Post, Comment 모델을 만들어 볼까요?
npx sequelize model:generate --name User --attributes name:string,email:string
npx sequelize model:generate --name Post --attributes title:string,content:text,userId:integer
npx sequelize model:generate --name Comment --attributes postId:integer,comment:text,userId:integer
위의 명령어들을 통해 /database/migration
과 /database/model
디렉토리에 Migration과 Model을 생성해줍니다.
주의 : attirbute를 입력할 때 space 없이 입력합니다. ex)
name:string,email:string
Foreign Key(userId, postId)에 NOT NULL이라는 제약조건을 넣습니다. 모델을 Eager loading 하기 위해서 입니다
userId: {
type: Sequelize.INTEGER,
allowNull: false,
},
postId: {
type: Sequelize.INTEGER,
allowNull: false,
},
/database/models/
에 다음과 같은 코드를 추가합니다.
// database/models/user.js
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
name: DataTypes.STRING,
email: DataTypes.STRING
}, {});
User.associate = function(models) {
// associations can be defined here
User.hasMany(models.Post, {
foreignKey: 'userId',
as: 'posts',
onDelete: 'CASCADE',
});
User.hasMany(models.Comment, {
foreignKey: 'userId',
as: 'comments',
onDelete: 'CASCADE',
});
};
return User;
};
// database/models/post.js
module.exports = (sequelize, DataTypes) => {
const Post = sequelize.define('Post', {
title: DataTypes.STRING,
content: DataTypes.TEXT,
userId: DataTypes.INTEGER
}, {});
Post.associate = function(models) {
// associations can be defined here
Post.hasMany(models.Comment, {
foreignKey: 'postId',
as: 'comments',
onDelete: 'CASCADE',
});
Post.belongsTo(models.User, {
foreignKey: 'userId',
as: 'author',
onDelete: 'CASCADE',
})
};
return Post;
};
// database/models/comment.js
module.exports = (sequelize, DataTypes) => {
const Comment = sequelize.define('Comment', {
postId: DataTypes.INTEGER,
comment: DataTypes.TEXT,
userId: DataTypes.INTEGER
}, {});
Comment.associate = function(models) {
// associations can be defined here
Comment.belongsTo(models.User, {
foreignKey: 'userId',
as: 'author'
});
Comment.belongsTo(models.Post, {
foreignKey: 'postId',
as: 'post'
});
};
return Comment;
};
테이블의 스키마도 다 정의 했으니(모델링) DB에 테이블을 만들어 봅시다.
npx sequelize db:migrate
성공했다면 DB에 User, Post, Comment 테이블이 만들어졌을 겁니다.
sequelize-cli를 이용하여 seed 파일을 만들어 봅시다.
npx sequelize seed:generate --name User
npx sequelize seed:generate --name Post
npx sequelize seed:generate --name Comment
위의 명령어를 실행하면 /database/seeders/
디렉토리 안에 YYYYMMDD-User.js, YYYYMMDD-Post.js, YYYYMMDD-Comment.js 가 만들어집니다.
실제 데이터를 테이블에 넣어 봅시다. 아래와 같이 작성하여 DB에 넣을 데이터를 만듭니다.
// database/seeds/YYYYMMDD-User.js
module.exports = {
up: (queryInterface, Sequelize) => queryInterface.bulkInsert(
'Users',
[
{
name: 'Jane Doe',
email: 'janedoe@example.com',
createdAt: new Date(),
updatedAt: new Date(),
},
{
name: 'Jon Doe',
email: 'jondoe@example.com',
createdAt: new Date(),
updatedAt: new Date(),
},
],
{},
),
down: (queryInterface, Sequelize) => queryInterface.bulkDelete('Users', null, {}),
};
// database/seeds/YYYYMMDD-Post.js
module.exports = {
up: (queryInterface, Sequelize) =>
queryInterface.bulkInsert(
"Posts",
[
{
userId: 1,
title: "hispotan de nu",
content:
"Nulla mollis molestie lorem. Quisque ut erat. Curabitur gravida nisi at nibh.",
createdAt: new Date(),
updatedAt: new Date()
},
{
userId: 2,
title: 'some dummy title',
content:
"Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque. Quisque porta volutpat erat.",
createdAt: new Date(),
updatedAt: new Date()
}
],
{}
),
down: (queryInterface, Sequelize) =>
queryInterface.bulkDelete("Posts", null, {})
};
// database/seeds/YYYYMMDD-Comment.js
module.exports = {
up: (queryInterface, Sequelize) =>
queryInterface.bulkInsert(
"Comments",
[
{
userId: 1,
postId: 2,
comment:
"Nulla mollis molestie lorem. Quisque ut erat. Curabitur gravida nisi at nibh.",
createdAt: new Date(),
updatedAt: new Date()
},
{
userId: 2,
postId: 1,
comment:
"Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque. Quisque porta volutpat erat.",
createdAt: new Date(),
updatedAt: new Date()
}
],
{}
),
down: (queryInterface, Sequelize) =>
queryInterface.bulkDelete("Comments", null, {})
};
sequelize-cli를 이용하여 데이터를 DB에 Seed 해봅시다
npx sequleize db:seed:all
성공했으면 데이터가 실제 테이블에 들어간 것입니다. 여기까지 Sequelize와 Sequelize-cli를 이용하여 Model, Migration 그리고 Seed까지 해봤습니다. 끝!