관련성을 가지며 중복이 없는 데이터들의 집합.
DBMS : 데이터베이스를 관리하는 시스템(DataBase Management System)
RDBMS : 관계형 데이터베이스 관리 시스템(Oracle, MySQL, MSSQL, PostgreSQL...)
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
$ brew install mysql
$ brew services start mysql
$ mysql_secure_installation
$ mysql -h localhost -u root -p
워크벤치는 데이터를 시각적으로 편리하게 관리하기 위한 프로그램
https://dev.mysql.com/downloads/workbench/ 를 통해 설치
$ mysql -h localhost -u root -p
mysql > CREATE SCHEMA nodejs;
mysql > use nodejs;
세미콜론(;) 필수!
CREATE_SCHEMA 같은 예약어는 되도록이면 대문자로 입력 권장
nodejs 같은 사용자 정의 이름과 구분하기 위함
mysql > 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 = '사용자 정보'
-> DEFAULT CHARSET=utf8
-> ENGINE=InnoDB;
INT : 정수를 의미함(소수까지 저장하고 싶다면 FLOAT, DOUBLE 자료형 사용)
CHAR(자릿수) : 반드시 자릿수의 문자열을 넣어줘야함
VARCHAR(자릿수) : 자릿수에 10을 입력시 0~10 길이의 문자열 입력 가능
TEXT : 몇백자 이내의 문자열은 VARCHAR로 처리하고, 그 이상일 경우에 TEXT 사용
TINYINT : -127부터 128까지의 정수를 저장할 때 사용. 0 또는 1만 사용시 boolean 값과 같은 역할을 할 수 있음
NULL : 빈칸 허용, NOT NULL 시 빈칸 불가하므로 데이터 입력 필수
AUTO_INCREMENT : 알아서 1부터 숫자를 저절로 올림
UNSIGNED : 숫자 자료형에 적용되는 옵션. 적용시 음수 입력 불가
ZEROFILL : 숫자의 자릿수가 고정되어 있을 때 사용.
ex) INT(4) -> 숫자 1을 입력시 0001이 됨
now() : 현재 시각을 넣으라는 뜻 CURRENT_TIMESTAMP과 동일
PRIMARY KEY : 해당 로우(raw)를 대표하는 고유한 값(기본 키)
UNIQUE INDEX : 해당 값이 고유해야 하는지에 대한 옵션
COMMENT : 테이블에 대한 보충 설명(필수아님)
DEFAULT CHARSET : utf8 미설정시 한글 입력 불가하므로 반드시 설정!
ENGINE : 여러가지가 있지만, MylSAM과 InnoDB가 제일 많이 사용됨.
만들어진 테이블 확인 명령어
mysql > DESC users;
테이블 제거
mysql > DROP TABLE users;
mysql > CREATE TABLE nodejs.comments(
-> id INT NOT NULL AUTO_INCREMENT,
-> commenter INT NOT NULL,
-> comment VARCHAR(100) NOT NULL,
-> created_at DATETIME NOT NULL DEFAULT now(),
-> PRIMARY KEY(id),
-> INDEX commenter_idx(commenter ASC),
-> CONSTRAINT commenter
-> FOREIGN KEY (commenter)
-> REFERENCES nodesjs.users (id)
-> ON DELETE CASCADE
-> ON UPDATE CASCADE)
-> COMMNET = '댓글'
-> DEFAULT CHARSET=utf8
-> ENGINE=InnoDB;
commenter 컬럼에는 댓글을 작성한 사용자의 id를 저장
외래키(forign key) : 다른 테이블의 기본 키를 저장하는 컬럼
CONSTRAINT [제약조건명]
FOREIGN KEY [컬럼명]
REFERENCES [참고하는 컬럼명]
위의 명령어를 통해 다른 테이블의 컬럼값 참조 가능
ON UPDATE, ON DELETE를 CASCADE로 설정함으로써, 사용자 정보 수정 여부에 따라 그와 관련된 댓글 정보도 수정하거나 삭제됨
sequalize.js는 node.js 에서 MySQL 작업을 쉽게 할 수 있도록 도와주는 라이브러리
sequelize는 ORM 으로 분류됨
ORM은 자바스크립트 객체와 데이터베이스의 릴레이션을 매핑해주는 도구
MySQL이외에도 MariaDB, PostgreSQL, SQLite, MSSQL 등 다른 데이터베이스도 사용가능
npx express learn-sequelize --view=pug
cd learn-sequelize
npm install
npm install sequelize mysql2
npm install -g sequelize-cli
sequelize init
models 폴더가 생성됨. 필요 없는 부분도 많아 다음과 같이 수정
models/index.js
const path = require('path');
const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development';
const config = require(path.join(__dirname, '..', 'config', 'config.json'))[env];
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
app.js
...
const sequelize = require('./models).sequelize;
sequelize.sync();
...
sync 메서드 사용하면 서버 실행 시 알아서 MySQL과 연동
models/user.js
module.exports = (sequelize, DataTypes) => {
return sequelize.define('user', {
name: {
type: DataTypes.STRING(20),
allowNull: false,
unique: true,
},
age: {
type: DataTypes.INTEGER.UNSIGNED,
allowNull: false,
},
married: {
type: DataTypes.BOOLEAN,
allowNull: false,
},
comment: {
type: DataTypes.TEXT,
allowNull: true,
},
created_at: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: sequelize.literal('now()'),
},
}, {
timestamps: false,
});
};
models/comment.js
module.exports = (sequelize, DataTypes) => {
return sequelize.define('comment', {
comment: {
type: DataTypes.STRING(100),
allowNull: false,
},
created_at: {
type: DataTypes.DATE,
allowNull: true,
defaultValue: sequelize.literal('now()'),
},
}, {
timestamps: false,
});
};
models/index.js
...
db.sequelize = sequelize;
db.Sequelize = Sequelize;
db.User = require('./user')(sequelize, Sequelize);
db.Comment = require('./comment')(sequelize, Sequelize);
module.exports = db;
...
config/config.json
{
"development": {
"username": "root",
"password": "[root 비밀번호]",
"database": "nodejs",
"host": "127.0.0.1",
"dialect": "mysql",
"operatorsAliases": false
},
...
}
password 에는 mysql 비밀번호 입력
operatorsAliases는 보안에 취약한 연산자를 사용할지 여부이므로 false 입력!
한 명의 사용자는 여러개의 댓글 작성 가능
하지만 댓글은 한명의 사용자만 참조가능
hasMany로 내보내줌
belongsTo로 가져옴
models/index.js
...
db.User.hasMany(db.Comment, {foreignKey: 'commenter', sourceKey: 'id'});
db.Comment.belongsTo(db.User, {foreignKey: 'commenter', targetKey: 'id'});
module.exports = db;
hasOne 사용
db.User.hasOne(db.Info, { foreignKey: 'user_id', sourceKey: 'id'});
db.Info.belongsTo(db.User, { foreignKey: 'user_id', targetKey: 'id'});
belongsToMany 사용
db.Post.belongsToMany(db.Hashtag, { through: 'PostHashtag' });
db.Hashtag.belongsToMany(db.Post, { through: 'PostHashtag' });
N:M 관계 특성상 새로운 모델이 생성됨
sequelize.js 쿼리를 통한 CRUD 작업
반드시 sequelize에서 정의한 자료형대로 넣어줘야됨
INSERT INTO nodejs.users (name, age, married, comment) VALUES ('zero', 24, 0, '자기소개1');
const { User } = require('../models')
User.create({
name: 'zero',
age: 24,
married: false,
comment: '자기소개1',
});
SELECT * FROM nodejs.users;
User.findAll({});
SELECT * FROM nodejs.users LIMIT 1;
user.find({});
SELECT name, married FROM nodejs.users;
User.findAll({
attributes: ['name', 'married'],
});
SELECT name, age FROM nodejs.users WHERE married = 1 AND age > 30;
const { User, Sequelize: { OP } } = require('../models');
User.findAll({
attributes: ['name', 'age'],
where: {
married: 1,
age: { [Op.gt]: 30 },
},
});
결괏값 : 기혼자 30살을 넘은 유저들의 이름과 나이만 가져옴
연산자
UPDATE nodejs.users SET comment = '바꿀 내용' WHERE id = 2;
User.update({
comment: '바꿀 내용',
}, {
where: { id: 2 },
})
DELETE FROM nodejs.users WHERE id = 2;
User.destroy({
where: { id: 2 },
});
CREATE TABLE nodejs.comments (
id INT NOT NULL AUTO_INCREMENT,
commenter INT NOT NULL,
comment VARCHAR(100) NOT NULL,
created_at DATETIME NOT NULL DEFAULT now(),
PRIMARY KEY(id),
INDEX commenter_idx (commenter ASC),
CONSTRAINT commenter
FOREIGN KEY (commenter)
REFERENCES nodejs.users (id)
ON DELETE CASCADE
ON UPDATE CASCADE)
COMMENT = '댓글'
DEFAULT CHARSET=utf8mb4
ENGINE=InnoDB;