이전 글에 이어서 이번 글에서는 데이터타입과 Seed 데이터 넣기, 모델과 테이블 연동에 대해 알아보자.
// ...
id: {
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING
},
// ...
각 속성에 설정했던 데이터 타입들은 데이터베이스의 테이블의 각 컬럼의 데이터타입으로 매핑되게 된다. 이때,
Sequelize.STRING
-> VARCHAR(256)
Sequelize.INTEGER
-> INTEGER
Sequelize.FLOAT
-> FLOAT
Sequelize.DATE
-> DATETIME
더 많은 데이터 타입에 대해 알고 싶다면, Sequelize 공식문서를 참고하자.
여기서 알아두면 좋은 점은 Sequelize.DataTypes.STRING
과 Sequelize.STRING
이 동일하다는 점이다.
// ...
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn('now')
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn('now')
}
// ...
이것 역시 데이터베이스를 배워보았다면, 그 개념이 명확할 것이다. 말 그대로 기본값이라는 의미로, 데이터를 새롭게 삽입할 때, 해당 컬럼이 비어 있으면(설정해주지 않으면) defaultValue에 있는 값이 자동으로 들어가게 된다.
이전 글에서 본 defaultValue: Sequelize.fn('now')
의 경우 MySQL 데이터베이스에서 사용할 수 있는 now라는 함수를 의미한다. Sequelize ORM에서는 이렇게 데이터베이스에서 지원하는 함수를 나타내기 위해 Sequelize.fn('함수 이름') 형식의 코드를 사용하게 된다. 이런 식으로 데이터베이스 자체의 함수도 사용할 수 있게 된다.
Seed 데이터를 넣기 위해서는 아래 작업을 수행해야 한다.
npx sequelize seed:generate --name initialMembers
module.exports = {
async up (queryInterface, Sequelize) {
await queryInterface.bulkInsert('Members', [
{
id: 1,
name: 'Alex',
team: 'engineering',
position: 'Server Developer',
emailAddress: 'alex@google.com',
phoneNumber: '010-xxxx-xxxx',
admissionDate: '2018/12/10',
birthday: '1994/11/08',
profileImage: 'profile1.png',
},
{
id: 2,
name: 'Benjamin',
team: 'engineering',
// ...
npx sequelize db:seed:all
이제 모델과 테이블을 연동해보자. 이미 이전 글에서 Member 모델을 생성을 완료했기 때문에 연결만 해주면 사용이 가능해진다.
하지만 그 전에, 자동으로 생성된 id
속성도 다루고 싶다면, Model에 추가해주어야 한다. 나는 Model.init()
메소드 내에 맨 위에 아래와 같이 추가해주었다. migrations 내의 파일과 다른점은 DataTypes
라는 객체를 받아오기 때문에 Sequelize.INTEGER
가 아닌 DataTypes.INTEGER
를 사용했다는 점이다.
// ./models/member.js
class Member extends Model {}
Member.init(
{
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER,
},
...
사실 .models/
디렉토리 내의 index.js
파일이 우리가 생성한 모델과 DB의 테이블을 연동하는 역할을 해준다.
사실 이미 쓰여져 있는 코드를 그대로 놔두어도 잘 작동한다. 하지만 기본적인 원리를 알아보기 위해 이번엔 직접 써보가면서 배워보자.
먼저 Sequelize
모듈과 설정 파일을 불러오자.
const Sequelize = require('sequelize');
const config = require('../config/config.json');
그리고 development
객체의 설정을 가져와서 sequelize
객체를 만들자.
이렇게 하면 우리가 처음에 설정했던 development
데이터베이스 설정대로 sequelize
객체를 생성해준다.
const = {
username, password, database, host, dialect
} = config.development;
const sequelize = new Sequelize(database, username, password, {
host,
dialect,
});
이제는 모델을 가져와야 한다. 그 전에 ./models/member.js
파일을 보면
module.exports = (sequelize, DataTypes) => {
class Member extends Model {
//... 생략 ...
위와 같이 sequlize
객체와 DataTypes
를 인자로 받는 함수가 공개되어 있음을 확인가능하다. 따라서 이 두 객체를 넣어주고 실행하면 Model 객체를 생성할 수 있게 된다.
const Member = require('./member')(sequelize, Sequelize.DataTypes);
이제 생성된 모델 객체를 사용하려면 외부에 공개해야 하는데, 관례적으로 db
라는 객체에 모델들을 넣어 공개하게 된다. 나중에 다른 테이블이 생긴다면 새로운 모델이 필요할 수 있기 때문이다.
const db = {}
db.Member = Member;
module.exports = db;
그 뒤에는 메인 파일에서 db를 가져와 사용하면 된다. 여기서는 메인 디렉토리의 app.js
파일에서 사용해보겠다.
// /app.js
// 특정 디렉토리만 적어줘도 그 아래에 있는
// index.js 파일을 자동으로 찾음
const db = require('./models');
const { Member } = db;
이제 이 Member 모델을 사용해서 데이터베이스 작업을 할 수 있게 된다.
사실 지금까지 작성한 코드를 잘 보면, 원래 기본적으로 작성되어 있던 코드와 그 원리가 같음을 알 수 있다. 따라서 기본코드를 그대로 쓰는 것을 권장한다. 따로 코드 작성을 더 하지 않아도 되고, 모델이 추가되더라도 자동으로 공개가 되기 때문에 우리가 직접 db객체에 추가해주지 않아도 된다.
기본적으로 작성되어 있던 index.js
는 아래와 같은데,
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.js')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(
config.database,
config.username,
config.password,
config
);
}
fs.readdirSync(__dirname)
.filter((file) => {
return (
file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js'
);
})
.forEach((file) => {
const model = require(path.join(__dirname, file))(
sequelize,
Sequelize.DataTypes
);
db[model.name] = model;
});
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
잘 보면 sequelize 자체도 db 객체에 담아 공개하는 것을 볼 수 있다. 이를 이용해 테이블 생성을 코드 내부에서도 구현이 가능하다. app.js
에서 sync()
메소드만 해주면 된다.
const db = require('./models');
db.sequelize.sync();
이제 다음 글에서는 데이터 조회 등 ORM을 이용해 데이터베이스를 다루는 방법에 대해 알아보겠다.
참고