지금까지는 모든 데이터를 변수에 저장했다.
데이터베이스
를 사용해야 한다.다양한 데이터베이스가 있지만, 여기서는 MySQL과 몽고디비를 사용한다.
- MySQL : SQL 언어를 사용하는 관계형 데이터베이스 관리 시스템의 대표 주자
- 몽고디비 : NoSQL의 대표 주자
데이터베이스는 관련성을 가지며 중복이 없는 데이터들의 집합이다.
이러한 데이터베이스를 관리하는 시스템을 DBMS
라고 한다.
보통 서버의 하드 디스크나 SSD 등의 저장 매체에 데이터를 저장한다.
저장 매체가 고장 나거나 사용자가 직접 데이터를 지우지 않는 이상 계속 데이터가 보존되므로 서버 종료 여부와 상관없이 데이터를 계속 사용할 수 있다.
또한, 서버에 데이터베이스를 올리면 여러 사람이 동시에 사용할 수 있다. 사람들에게 각각 다른 권한을 줘서 어떤 사람은 읽기만 가능하고, 어떤 사람은 모든 작업을 가능하게 할 수 있다.
데이터베이스를 관리하는 DBMS
중에는 RDBMS
라고 부르는 관계형 DBMS가 많이 사용된다. 대표적인 RDBMS로 Oracle, MySQL, MSSQL 등이 있다. 이들은 SQL이라는 언어를 사용해 데이터를 관리한다.
Homebrew를 통해 설치하기
brew install mysql // 설치
brew services start mysql // mysql 시작
mysql_secure_installation // root 비밀번호 설정
mysql -h localhost -u root -p // 접속하기(비밀번호 입력)
콘솔로는 데이터를 한눈에 보기에 무리가 있으므로 워크벤치라는 프로그램을 사용하면 데이터베이스 내부에 저자오딘 데이터를 시각적으로 관리할 수 있어 편리하다.
(필수적인 것은 아니며 콘솔로도 동일한 작업을 할 수 있다.)
설치
brew install --cask mysqlworkbench
버전 8.0.21로 설치하기!
보안때문에 안열리면 우클릭 -> 열기
MySQL 프롬프트에 접속
mysql -h localhost -u root -p
데이터베이스 생성
데이터베이스명
: 데이터베이스 생성하는 명령어 (스키마는 데이터베이스와 같은 개념)CREATE SCHEMA `nodejs` DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci;
테이블이란 데이터가 들어갈 수 있는 틀을 의미하며, 테이블에 맞는 데이터만 들어갈 수 있다.
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 = '사용자 정보'
ENGINE = InnoDB;
사용할 데이터베이스 선택
USE nodejs;
만들어진 테이블 확인하기
DESC 테이블명
DESC users;
테이블 제거하기
DROP TABLE 테이블명
DROP TABLE users;
CRUD는 데이터베이스에서 많이 수행하는 네 가지 작업을 일컫는다.
Create는 데이터를 생성해서 데이터베이스에 넣는 작업이다.
명령어 : INSERT INTO 테이블명 (컬럼1, 컬럼2,,) VALUES (값1, 값2,,)
예시
INSERT INTO nodejs.users (name, age, married, comment) VALUES ('zero', 24, 0, '자기소개1');
Read는 데이터베이스에 있는 데이터를 조회하는 작업이다.
명령어 : SELECT * FROM 테이블명
예시
SELECT * FROM nodejs.users;
실행 결과
특정 컬럼만 조회하기
SELECT name, married FROM nodejs.users;
특정 조건을 가진 데이터만 조회하기
SELECT name, age FROM nodejs.users WHERE married = 1 AND age > 30;
정렬하기
SELECT id, name FROM nodejs.users ORDER BY age DESC;
특정 열만 조회하기
LIMIT 숫자
SELECT name, married FROM nodejs.users LIMIT 1;
Update는 데이터베이스에 있는 데이터를 수정하는 작업이다.
명령어 : UPDATE 테이블명 SET 컬럼명='바꿀값' WHERE 조건
예시
UPDATE nodejs.users SET comment = '바꿀 내용' WHERE id = 2;
Delete는 데이터베이스에 있는 데이터를 삭제하는 작업이다.
명령어 : DELETE FROM 테이블명 WHERE 조건
예시
DELETE FROM nodejs WHERE id = 2;
시퀄라이즈는 MySQL 작업을 쉽게 할 수 있도록 도와주는 라이브러리이다.
시퀄라이즈는 ORM(Object-relational Mapping)으로 분류된다.
ORM은 자바스크립트 객체와 데이터베이스의 릴레이션을 매핑해주는 도구이다.
시퀄라이즈를 쓰는 이유는 자바스크립트 구문을 알아서 SQL로 바꿔주기 때문이다. 따라서 SQL 언어를 직접 사용하지 않고도 자바스크립트만으로 MySQL을 조작할 수 있으며, SQL을 몰라도 MySQL을 어느 정도 다룰 수 있게 된다.
설치
sequelize, sequelize-cli(시퀄라이즈 명령어를 실행하기 위한 패키지), mysql2(MySQL과 시퀄라이즈를 이어주는 드라이버) 패키지 설치
npm i express morgan nunjucks sequelize sequelize-cli mysql2
npm i -D nodemon
설치 완료 후 sequelize init 명령어 호출.
전역 설치 없이 명령어로 사용하려면 앞에 npx 붙이기
npx sequelize init
app.js
const express = require('express');
const path = require('path');
const morgan = require('morgan');
const nunjucks = require('nunjucks');
const { sequelize } = require('./models');
const indexRouter = require('./routes');
const usersRouter = require('./routes/users');
const commentsRouter = require('./routes/comments');
const app = express();
app.set('port', process.env.PORT || 3001);
app.set('view engine', 'html');
nunjucks.configure('views', {
express: app,
watch: true,
});
sequelize.sync({ force: false })
.then(() => {
console.log('데이터베이스 연결 성공');
})
.catch((err) => {
console.error(err);
});
app.use(morgan('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/comments', commentsRouter);
app.use((req, res, next) => {
const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`);
error.status = 404;
next(error);
});
app.use((err, req, res, next) => {
res.locals.message = err.message;
res.locals.error = process.env.NODE_ENV !== 'production' ? err : {};
res.status(err.status || 500);
res.render('error');
});
app.listen(app.get('port'), () => {
console.log(app.get('port'), '번 포트에서 대기 중');
});
MySQL과 연동할 때는 config 폴더 안의 config.json 정보가 사용된다. 다음과 같이 수정한다.
config/config.json
{
"development": {
"username": "root",
"password": "root 비밀번호", // 내 MySQL 비밀번호
"database": "nodejs",
"host": "127.0.0.1",
"dialect": "mysql"
},
}
시퀄라이즈는 모델과 MySQL의 테이블을 연결해주는 역할을 한다.
(시퀄라이즈는 기본적으로 모델 이름은 단수로, 테이블 이름은 복수형으로 사용한다.)
static initiate 메서드에는 테이블에 대한 설정을 하고, static associate 메서드에는 다른 모델과의 관계를 적는다.
models/user.js
const Sequelize = require('sequelize');
class User extends Sequelize.Model {
static initiate(sequelize) {
User.init({
name: {
type: Sequelize.STRING(20),
allowNull: false,
unique: true,
},
age: {
type: Sequelize.INTEGER.UNSIGNED,
allowNull: false,
},
married: {
type: Sequelize.BOOLEAN,
allowNull: false,
},
comment: {
type: Sequelize.TEXT,
allowNull: true,
},
created_at: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.NOW,
},
}, {
sequelize,
timestamps: false,
underscored: false,
modelName: 'User',
tableName: 'users',
paranoid: false,
charset: 'utf8',
collate: 'utf8_general_ci',
});
}
static associate(db) {
db.User.hasMany(db.Comment, { foreignKey: 'commenter', sourceKey: 'id' });
}
};
module.exports = User;
모델을 생성했다면 models/index.js와 연결한다.
const Sequelize = require('sequelize');
const User = require('./user');
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
db.User = User; // db에 모델담기
User.initiate(sequelize); // static initiate 메서드 호출
User.associate(db); // 다른 테이블과의 관계 연결
module.exports = db;
MySQL에서는 JOIN이라는 기능으로 여러 테이블 간의 관계를 파악해 결과를 도출한다. 시퀄라이즈는 JOIN 기능도 알아서 구현한다. 대신 테이블 간에 어떠한 관계가 있는지 시퀄라이즈에 알려야 한다.
시퀄라이즈는 일대다 관계를 hasMany라는 메서드로 표현한다. 반대로 belongsTo 메서드도 있다.
(다른 모델의 정보가 들어가는 테이블에는 belongsTo를 사용한다.)
모델 각각의 static associate 메서드에 넣는다.
models/user.js
static.associate(db){
db.User.hasMany(db.Comment, {foreginKey: 'commenter' sourceKey: 'id'})
}
models/comment.js
static.associate(db){
db.Comment.belongsTo(db.User, {foreginKey: 'commenter' targetKey: 'id'})
}
1:1 관계에서는 hasMany 메서드 대신 hasOne 메서드를 사용한다.
N:M 관게를 표현하기 위한 belongsToMany 메서드가 있다.
시퀄라이즈로 CRUD 작업을 하려면 먼저 시퀄라이즈 쿼리를 알아야 한다.
models 모듈에서 User 모델을 불러와 create 메서드를 사용하면 된다.
const {User} = require('../models');
User.create({
name : 'zero',
age: 24,
married: false,
comment: '자기소개1',
})
findAll / findOne 메서드 사용
User.findAll({}); // users 테이블의 모든 데이터 조회
User.findOne({}); // users 테이블의 데이터 하나만 가져옴
User.findAll({
attributes: ['name', 'married'] // 원하는 컬럼만 가져오기
})
update 메서드 사용
User.update({
comment: '바꿀 내용', // 수정할 내용
},{
where: {id: 2}, // 어떤 로우를 수정할지에 대한 조건
})
destroy 메서드 사용
User.destroy({
where: {id:2}
})