npx 를 이용한 시퀄라이즈 연결
npx 로 만든 프로젝트 구조에서 시퀄라이즈 연결 방법에 대해 다룬다. 개요는 아래와 같다.
- npx 를 이용한 구조 생성
- config.js 수정
- index.js 분석
- model 생성
- sync() 메서드를 호출해 sequelize 실행
npx 를 이용한 구조 생성
express 와 시퀄라이즈를 이용한 프로젝트를 구성하기 위한 기본적인 설정들이다.
package.json 생성
npm init -y
mysql2 는 MySQL 데이터베이스를 의미하는 것이 아닌 Node.js 와 MySQL 을 연결해주는 역할을 하는 드라이버다. sequelize-cli 는 시퀄라이즈 명령어를 사용할 수 있게 해주는 패키지다.
npm i express sequelize mysql2
npm i -D sequelize-cli
npx 명령어로 sequelize-cli 를 이용해 시퀄라이즈 구조를 생성한다.
npx sequelize init
config 폴더, migrations 폴더, models 폴더,seeders 폴더가 생성된다.
npx
npx는 npm 레지스트리에 올라가있는 패키지를 쉽게 설치하고 관리할 수 있도록 도와주는 CLI 도구다. 쉽게 말해 npm 을 좀 더 편하게 사용하기 위해 npm 에서 제공해주는 것이다.현재 npm 버전에 npx가 설치되어 있는지 확인한다.
which npx
config.json 수정
username 과 password , database 이름을 설정해준다.
{
"development": {
"username": "user_name",
"password": "database_password",
"database": "database_name",
...
}
models/index.js 분석
기본적으로 npx sequelize init
명령어를 입력하면 models 폴더 안에 아래와같이 index.js 가 생성된다. models 폴더는 Model을 정의한 js 파일들을 모아놓은 폴더다.
models/index.js 파일은 다음 과정을 수행한다.
- /config/config.json 파일의 설정 값을 읽어 sequelize를 생성
- models 폴더 아래에 존재하는 js 파일을 모두 로딩
- db 객체에 Model을 정의하여 반환
정리하면, 여러 모델들을 한 객체( 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.json')[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;
각각 fs 모듈, path 모듈, sequelize 라이브러리를 임포트한다.
fs 모듈은 FileSystem의 약자로 파일 처리와 관련된 모듈이다.
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
path.basename(path) 은 인자로 경로를 받고 해당 파일이름을 출력한다.
아래 결과를 통해 직관적으로 이해할 수 있다.
console.log(__filename);
console.log(path.basename(__filename));
실행결과
/home/ywoosang/projects/test.js
test.js
__filename
을 이용해 현재 파일의 경로를 입력하고, path.basename 을 이용해 파일 이름을 basename 변수에 할당한다.
const basename = path.basename(__filename);
node 환경변수 process.env 에 NODE_ENV 를 별도로 설정해놓았다면 그 값을 사용하고, 아니라면 기본 값으로 'development' 를 사용한다. 이렇게 해주면 NODE_ENV 가 따로 지정이 안되어 있더라도 development 모드로 지정되게 해줄 수 있다.
const env = process.env.NODE_ENV || 'development';
NODE_ENV 값을 설정하는 방법
Linux, Mac OSexport NODE_ENV=production
Windows
set NODE_ENV=production
아래 처럼 NODE_ENV 값에 따라 개발과 배포용 소스를 따로 분리해서 작업할 수 있다.
if (process.env.NODE_ENV == 'production') { console.log("Production Mode"); } else if (process.env.NODE_ENV == 'development') { console.log("Development Mode"); }
config 폴더 안에있는 config.json 에서 env 에 해당하는 오브젝트를 가져와 config 변수에 할당한다.
const config = require(__dirname + '/../config/config.json')[env];
예를들어 env='development' 일경우 아래 오브젝트가 할당된다.
{
"username": "user_name",
"password": "database_password",
"database": "database_name",
...
}
db 변수에 빈 오브젝트를 할당한다.
const db = {};
sequelize 변수를 선언한다. config.use_env_variable 가 존재한다면, 해당 설정으로 시퀄라이즈 인스턴스를 생성한다. 존재하지 않는다면 config 변수에 할당되어있는 오브젝트의 database, username, password 를 기반으로 시퀄라이즈 인스턴스를 생성한다.
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() 메소드를 이용해 인자로 받은 디렉토리의 파일들을 동기적으로 읽는다. filter 반복문을 돌면서 .
으로 시작하지 않고 이름이 index.js
가 아니며 .js
확장자를 가진 파일들을 배열로 반환한다. forEach 를이용해 읽어온 js 파일들 하나씩 반복한다. 현재 index.js 가 있는 디렉토리는 models 디렉토리기 때문에 js 파일들은 모두 데이터베이스 모델이라고 가정하고 각 모델들을 모델이름을 key 로 모델을 value 로 db 오브젝트에 집어넣는다.
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;
});
반복문을 돌면서 associate() 메서드를 통해 Model 사이의 관계를 정의한다.
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
모델 정의
데이터베이스 모델을 정의하는 방법에 대해서는 공식문서 번역글 에서 자세하게 다루고 있다.
별도로, npx 를 이용해 생성한 index.js 를 이용하기 위해서는 데이터베이스 모델을 다르게 정의할 필요성이 있다.
위 index.js 에서 다음과 같이 require 로 임포트한 부분을 볼 수 있는데, 각 모델을 정의한 파일에서 export 해온 대상이 오브젝트가 아니라 함수인 것을 유추할 수 있다.
require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
혹시 이해가 가지 않는다면 아래 의미를 생각해보자. 함수를 require 로 불러오고 실행한 것이다.
require(..)(sequelize, Sequelize.DataTypes)
따라서 모델을 정의한 js 파일에서 다음과 같이 function 을 export 해준다.
module.exports = function(sequelize, DataTypes){ ... }
모델을 정의하는 방법 중 하나인
define() 을 이용한다. sequelize.define('객체 이름', 스키마 정의, 테이블 설정) 처럼 사용한다. 예를 들기 위해 사용자를 나타내는 user 테이블을 정의해보겠다. sequelize 는 index.js 에서 인자로 전송된 변수로, Sequelize 인스턴스를 담고 있다. DataTypes 는 index.js 에서 인자로 넘겨준 Sequelize.DataTypes 이다.
# user.js
module.exports = function(sequelize, DataTypes){
let user = sequelize.define("User", {
userID: {
filed: "user_id",
type: DataTypes.STRING(50),
unique: true,
allowNull: false
},
password: {
field: "password",
type: DataTypes.STRING(30),
allowNull: false
}
}, {
underscored: true,
freezeTableName: true,
tableName: "user"
});
return user;
}
이렇게 테이블을 정의하면, /models/index.js에서 반복문을 돌면서 models 폴더 내에 있는 파일들을 읽어들여 모델들을 db 오브젝트 안에 취합한다. 그 후 다시 반복문을 돌면서 관계가 정의된다. 따라서, index.js에서 users.js 파일을 읽어들여 모델로 정의되고 관계가 생긴다.
sync() 를 이용해 시퀄라이즈 연결
시퀄라이즈는 데이터 조작과 정의를 지원하기 때문에 이미 만들어진 테이블에 Model을 매핑할 수 있고, DB에 테이블이 없는 상태라면 정의한 Model을 바탕으로 테이블을 생성할 수도 있다.
이를 수행하는 메소드가 sync() 이며, sync()는 모델에서 정의한 이름을 갖는 테이블이 존재하지 않을 경우에만 동작한다. /models/index.js 파일에서 정의한 모델들을 바탕으로 실제로 Model을 등록하는 역할을 한다.
app.js 파일 상단에 다음 코드를 작성한다.
...
sequelize.sync({force : false})
.then(()=> {
console.log('database connect');
}).catch((err)=> {
console.err(err);
});
...
콘솔에 database connect 가 출력되면 정상적으로 연결된 것이다.
참고
path 관련 -
https://yohanpro.com/posts/js/node-path
Sequelize 환경변수 -
https://yangeok.github.io/node.js/2019/06/11/sequelizerc.html
모델 정의 -
https://analogcoding.tistory.com/125
시퀄라이즈 공식문서 (인스턴스) -
https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#instance-constructor-constructor
sync 메소드 -
https://victorydntmd.tistory.com/26?category=677306
Author And Source
이 문제에 관하여(npx 를 이용한 시퀄라이즈 연결), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@ywoosang/시퀄라이즈-연결-및-기본-세팅저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)