7. MySQL

진영민·2022년 9월 6일
0

Node.js 교과서

목록 보기
6/13

해당 글은 Node.js 교과서의 내용을 요약, 정리한 글입니다.

Database

데이터베이스는 관련성을 가지며 중복이 없는 데이터들의 집합이며, 이러한 데이터베이스를 관리하는 시스템을 DBMS라고 한다.

DBMS중에서 RDBMS라고 부르는 관계형 DBMS가 많이 사용된다.

MySQL 설치하기

MySQL 데이터베이스 및 테이블 생성하기

스키마 생성하기

CREATE SCHEMA 'nodejs' DEFAULT CHARACTER SET utf8;

해당 명령어를 입력하여 스키마를 생성한다.
use nodejs를 이용하여 node.js데이터베이스를 사용하겠다는 것을 알린다.

테이블 생성하기

CREATE TABLE nodejs.users(
	->id INT NOT NULL AUTO_INCREMENT,
    ->name VARCHAR(20) NOT NULL
    ->PRIMARY KEY(id),
    ->UNIQUE INDEX name_UNIQUE (name ASC))
    ->COMMENT = '사용자 정보'
    ->DEFAULT CHARACTER SET = utf8
    ->ENGINE = InnoDB;

자료형

INT: 정수를 의미함.
VARCHAR: CHAR은 고정 길이, VARCHAR는 가변 길이이다.
TEST: 긴 글을 저장할때 사용, 수백 자 보다 길면 TEXT를 사용하곤 한다.
TINYINT: -128부터 127까지의 정수를 저장할 때 사용한다. BOOLEAN과 같은 역할을 할 수 있습니다.
DATETIME: 날짜와 시간에 대한 정보

옵션

NULL, NOT NULL은 빈칸을 허용할 지 묻는 옵션
AUTO_INCREMENT: 숫자를 자동으로 올리기
UNSIGNED: 음수를 무시하고 숫자를 표시
ZEROFILL: 비어 있는 자리에 모두 0을 채워 넣는다.
DEFAULT: 해당 칼럼 값이 없다면 기본값으로 대신 넣는다.
PRIMARY KEY: 로우를 대표하는 고유한 값
UNIQUE INDEX: 해당 값이 고유해야 하는지에 대한 옵션

테이블 자체에 대한 설정

COMMENT: 테이블에 대한 보충 설명
DEFAULT CHARACTER SET: utf8로 설정하지 않으면 입력되지 않는다.
ENGINE: 여러 가지가 있지만, MyISAM과 InnoDB가 제일 많이 사용된다.

명령어

DROP TABLE users;
//테이블을 제거한다.

CREATE TABLE [db이름].[테이블 이름](설정값)
//테이블을 생성한다.

SHOW TABLES;
//테이블을 확인한다.

CRUD 작업

create 생성

INSERT INTO nodejs.users (name, age, married, comment) VALUES('zero',24,0,'자기소개');

Read 조회

SELECT * FROM modejs.users;

//where문으로 특정 조건을 가진 데이터만 조회할 수 있습니다.
SELECT name, age FROM nodejs.users WHERE married = 1 AND age > 30;

//OR도 사용할 수 있습니다.
SELECT id, name FROM nodejs.users WHERE married=0 OR age > 30;

//ORDER BY로 정렬이 가능하다.
SELECT id, name FROM nodejs.users ORDER BY age DESC;

//조회할 로우 개수를 설정한다.
SELECT id, name FROM nodejs.users ORDER BY age DESC LIMIT 1;

//로우 개수를 설정하면서 몇 개를 건너뛸지 설정한다.
//게시판 등의 페이징에 유용하다.
SELECT id, name FROM nodejs.users ORDER BY age DESC LIMIT 1 OFFSET 1;

Update(수정)

UPDATE nodejs.users SET comment='바꿀 내용' WHERE id=2;

Delete(삭제)

데이터베이스에 있는 데이터를 삭제하는 방법
DELETE FROM nodejs.users WHERE id = 2;

시퀄라이즈 사용하기

$npm i express morgan nunjucks sequelize sequelize-cli mysql2
$npm i -D nodemon
$npx sequelize init
//modules/index.js
const Sequelize = require('sequelize');

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;

module.exports = db;

MySQL 연결하기

//app.js
const express = require('express');
const path = require('path');
const morgan = require('morgan');
const nunjucks = require('nunjucks');

const{sequelize} = require('./models');

const app = express();
app.set('port', process.env.PORT||3001);
app.set('view engine','html');
nunjucks.configure('vies',{
    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((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.json에 password, database등을 수정한다.

모델 정의하기

const Sequelize = require('sequelize');

module.exports = class User extends Sequelize.Model{
    static init(sequelize){
        return super.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:'user',
            paranoid:false,
            charset:'utf8',
            collate:'utf8_general_ci',
        });
    }
    static associate(db){}
};

관계 정의하기

테이블과 테이블간의 관계를 정의할 수 있는데, 1:1, 1:N, N:M 으로 정의할 수 있다.

1:N

시퀄라이즈에서는 1:N의 관계를 hasMany라는 메서드로 표현한다. 이 메서드를 이용하면 users 테이블의 로우 하나를 불러올 때 연결된 comments 테이블의 로우들도 같이 불러올 수 있다. 반대로 belongsTo 메서드를 사용하면 comments 테이블의 로우를 불러올 때 연결된 users테이블의 로우를 가져온다. 즉, 다른 모델의 정보가 들어가는 테이블에 사용한다.

1:1

1:1관계에서는 hasOne메서드를 사용한다. 여기서도 반대의 경우 belongsTo 메서드를 사용하는데, 반대로되면 안된다.

N:M

N:M 관계를 표현하기 위해 belongsToMany 메서드를 사용한다. 이 관계에서는 양쪽 보델에 모두 belongToMany 메서드를 사용한다.

관계 쿼리

관계 쿼리란 MySQL의 JOIN 기능으로 시퀄라이즈의 include 속성을 사용한다.

findOne이나 findAll 메서드를 호출할 때 프로미스의 결과로 모델을 반환한다(findAll은 모두 찾는 것이므로 모델의 배열을 반환한다).

  include: [{
    model: Comment,
  }]
});
console.log(user.Comments); //사용자 댓글

특정 사용자를 가져오면서 그 사람의 댓글까지 모두 가져오는 시퀄라이즈문이다. 어떤 모델과 관계가 있는지 include 배열에 넣어주면 된다. 이때, 배열인 이유는 다양한 모델과 관계가 있을 수 있기 때문이다.

관계를 설정했다면 getCOmments(조회) 이외에도 setComments(수정), addComment(하나 생성), addComments(여러개 생성), removeComments(삭제) 메서드를 지원한다.

//관계 설정시 as로 등록
db.User.hasMany(db.Comment, {
  foreignKey: 'commenter',
  sourceKey: 'id',
  as: 'Answers'
});
//쿼리할 때
const user = await User.findOne({});
const comments = await user.getAnswers();
console.log(comments); //사용자 댓글

** include나 관계 쿼리 메서드에서도 where이나 attributes 같은 옵션을 사용할 수 있다.

SQL 쿼리하기

만약 시퀄라이즈의 쿼리를 사용하기 싫거나 잘 모르겠다면 직접 SQL문을 통해 쿼리할 수 있다.

const [result, metadata] = await sequelize.query('SELECT * from comments');
console.log(result);
profile
코린이

0개의 댓글