상세 컨텐츠

본문 제목

[노드 1팀] 7장. MySQL

24-25/Node.js 1

by gooroominuna 2024. 11. 29. 10:00

본문

728x90

7.1. 데이터베이스란?

데이터베이스 : 관련성을 가지며 중복이 없는 데이터들의 집합

DBMS : 데이터베이스를 관리하는 시스템

  • 서버의 하드 디스크나 SSD 등의 저장 매체에 데이터 저장
  • 서버에 올리면 여러 사람이 동시에 사용 가능
  • 각각 다른 권한을 줘서 어떤 사람을 읽기만 가능하고, 어떤 사람은 모든 작업을 가능하게 할 수 있음

RDMS라고 부르는 관계형 DBMS가 많이 사용

 

(MySQL, 워크밴치 설치 과정 생략)

 

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

1. 데이터베이스 생성하기

CREATE SCHEMA [데이터베이스명] : 데이터베이스를 생성하는 명령어 (스키마 = 데이터베이스)

use nodejs; : nodejs 데이터베이스를 사용하겠다는 것을 알림

DEFAULT CHARACTER SET ufg8mb4 DEFAULT COLLATE utf8 mb4_general_ci를 붙여 한글, 이모티콘 사용 가능

  • CREATE SCHEMA와 같이 기본적으로 알고 있는 구문을 예약어라고 한다.
  • 사용자가 직접 만든 이름과 구분하기 위해 대문자로 쓰는 것을 권장

2. 테이블 생성하기

CREATE TABLE [데이터베이스명.테이블명] : 테이블을 생성하는 명령어

뒤에 콤마(,)로 구분하여 컬럼들을 만든다.

컬럼 옆에는 컬럼의 자료형을 선언한다. (INT, VARCHAR(자릿수), TINYINT, TEXT, DATETIME

자료형 뒤에는 다양한 옵션들을 붙인다. NOT NULL, NULL, UNSIGNED, AUTO_INCREMENT, ZEROFILL, DEFAULT

 

PRIMARY KEY : 기본 키로 로우를 대표하는 고유한 값을 의미

COMMENT : 테이블에 대한 보충 설명, 필수 아님

ENGINE : MyISAM, InnoDB가 많이 사용

 

DESC [테이블명] : 만들어진 테이블을 확인하는 명령어

DROP TABLE [테이블명] : 테이블을 제거하는 명령어

 

외래키(foreign key) : 다른 테이블의 기본 키를 저장하는 컬럼

CONSTRAINT [제약조건명] FOREIGN KEY [컬럼명] REFERENCES [참고하는 컬럼명] : 외래키 지정

CASCADE 설정 : 사용자 정보가 수정되거나 삭제되면 그것과 연결된 정보도 같이 수정하거나 삭제

SHOW TABLES; : 테이블 이름을 띄움

7.5. CRUD 작업하기

CRUD : create, read, update, delete의 첫 글자를 모은 두 문자어

1. Create (생성)

데이터를 생성해서 데이터베이스에 넣는 작업

INSERT INTO [테이블명] ([컬럼1], [컬럼2], ... ) VALUES ([값1], [값2], ...) : 데이터를 넣는 명령어

2. Read (조회)

데이터베이스에 있는 데이터를 조회하는 작업

SELECT * FROM [테이블명] : 테이블의 모든 데이터를 조회하는 sql문

  • 조회를 원하는 컬럼은 SELECT 다음에 넣으면 해당 컬럼만 나온다.
  • WHERE 절을 사용하여 특정 조건을 가진 데이터만 조회할 수 있다.
  • AND를 사용하여 조건들을 모두 만족하는 데이터를 찾을 수 있다.
  • OR을 사용하여 조건들 중 어느 하나라도 만족하는 데이터를 찾을 수 있다.
  • ORDER BY [컬럼명] [ASC|DESC] : 원하는 대로 정렬 가능하다.
  • LIMIT [숫자]를 사용하여 조회할 로우 개수를 설정할 수 있다.
  • OFFSET [건너뛸 숫자] 키워드를 사용하여 건너뛸지 설정할 수 있다.

3. Update (수정)

데이터베이스에 있는 데이터를 수정하는 작업

UPDATE [테이블명] SET [컬럼명=바꿀 값] WHERE [조건] : 수정 명령어

4. Delete (삭제)

데이터베이스에 있는 데이터를 삭제하는 작업

DELETE FROM  [테이블명] WHERE [조건] : 삭제 명령어

7.6. 시퀄라이즈 사용하기

시퀄라이즈 : mysql 작업을 쉽게 할 수 있도록 도와주는 라이브러리

ORM : 자바스크립트 객체와 데이터베이스의 릴레이션을 매핑해 주는 도구로 시퀄라이즈가 이에 분류됨

시퀄라이즈를 쓰면 자바스크립트 구문을 알아서 SQL로 바꿔준다.

npm i express morgan nunjucks sequelize sequelize-cli mysql2
npm i -D nodemon

npx sequelize init

- 시퀄라이즈에 필요한 sequelize와 sezuelize-cli, mysql2 패키지 설치

 

1. MySQL 연결하기

//app.js 생성하고 익스프레스와 시퀄라이즈 연결 코드 작성
const express = require('express');
const path = require('path');
const morgan = require('morgan');
const nunjucks = require('nunjucks');

const { sequelize } = require('./models'); 
// = require('./models/index.js');
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 })
//true로 설정하면 서버를 실행할 때마다 테이블을 재생성함.
//테이블을 잘못 만든 경우 true로 설정하면 됨
  .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'), '번 포트에서 대기 중');
});
//config.json
{
  "development": {
    "username": "root",
    "password": {비밀번호}, //mysql 비밀번호
    "database": "nodejs", //nodejs로 바꾸기
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  ...
 }

2. 모델 정의하기

//models/user.js
const Sequelize = require('sequelize');

class User extends Sequelize.Model {
  static initiate(sequelize) {
    User.init({
      name: {
        type: Sequelize.STRING(20), //varchar
        allowNull: false, //not null
        unique: true, //unique
      },
      age: {
        type: Sequelize.INTEGER.UNSIGNED, //int
        allowNull: false,
      },
      married: {
        type: Sequelize.BOOLEAN, //tinyint
        allowNull: false,
      },
      comment: {
        type: Sequelize.TEXT,
        allowNull: true,
      },
      created_at: {
        type: Sequelize.DATE, //datetime
        allowNull: false,
        defaultValue: Sequelize.NOW, //default now()
      },
    }, {
      sequelize,
      //static initiate 메서드의 매개변수와 연결되는 옵션
      timestamps: false,
      //true면 시퀄라이즈는 createaAt, updateAt컬럼 추가, 각각 로우가 생성, 수정될 때 시간 입력
      underscored: false,
      //캐멀 케이스를 스네이크 케이스로 바꾸는 옵션
      modelName: 'User',
      //모델 이름 설정
      tableName: 'users',
      //테이블 이름 설정
      paranoid: false,
      //true로 설정하면 deletedAt컬럼 생기고 로우 삭제할 때 시간 입력
      charset: 'utf8',
      collate: 'utf8_general_ci',
    });
  }

  static associate(db) {
    db.User.hasMany(db.Comment, { foreignKey: 'commenter', sourceKey: 'id' });
  }
};

module.exports = User;
//models/comment.js
const Sequelize = require("sequelize");
const { FOREIGNKEYS } = require("sequelize/lib/query-types");

class Comment extends Sequelize.Model {
  static initiate(sequelize) {
    Comment.init(
      {
        comment: {
          type: Sequelize.STRING(100),
          allowNull: false,
        },
        created_at: {
          type: Sequelize.DATE,
          allowNull: true,
          defaultValue: Sequelize.NOW,
        },
      },
      {
        sequelize,
        timestamps: false,
        modelName: "Comment",
        tableName: "comments",
        paranoid: false,
        charset: "utf8mb4",
        collate: "utf8mb4_general_ci",
      }
    );
  }

  static associate(db) {
    db.Comment.belongsTo(db.User, { FOREIGNKEYS: "commenter", targetKey: "id" });
  }
}

module.exports = Comment;
//models/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;

db.User = User;
db.Comment = Comment;

User.initiate(sequelize);
Comment.initiate(sequelize);

User.associate(db);
Comment.associate(db);

module.exports = db;

- 생성한 모델 index.js에 연결

3. 관계 정의하기

1:N 관계 : hasMany, belongsTo 사용

//user.js

static associate(db) {
	db.User.hasMany(db.Comment, { foreignKey: "commenter", sourceKey: "id" });
}

//comment.js

static associate(db) {
	db.Comment.belongsTo(db.User, { FOREIGNKEYS: "commenter", targetKey: "id" });
}

hasMany에서 sourceKey 속성에 id / belongsTo에서 targetKey 속성에 id / 모두 User 모델의 id

 

1:1 관계 : hasOne, belongsTo 사용

N:M 관계 : belongsToMany 사용

4. 쿼리 알아보기

//로우 생성
insert into values (~~)
=
User.create({
	name:'zero',
    age: 24,
    married: false,
    comment: '자기소개1',
});

select * from nodejs.users;
=
User.findAll({});

select name, married from nodejs.users;
=
User.findAll({
	attribues: ['name', 'married'],
});

select name, age from nodejs.users where married = 1 and age > 30;
=
User.findAll({
	attributes: ['name', 'age'],
    where: {
    	married: true,
        age: { [0p.gt]: 30},
    },
});

select id, name from users order by age desc limit 1 offset 1;
=
User.findAll({
	attributes: ['id', 'name'],
    order: ['age', 'DESC'],
    limit: 1,
    offset: 1,
});

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},
});

 

관계 쿼리

관계가 맺어져 있는 테이블을 모두 가지고 오고 싶다면 include 속성을 사용한다.

const user = await User.findOne({
	include: [{
    	model: Comment,
    }]
});

 

관계를 설정하고 나면 getComments(조회), setComments(수정), addCommment(하나 생성), addComments(여러 개 생성), removeComments(삭제) 메서드를 지원한다.

 

SQL 쿼리

시퀄라이즈의 쿼리 사용을 추천하지만 할 수 없는 경우 이와 같이 sql 쿼리 작성할 수 있다.

const [result, metadata] = await sequelize.query('select * from comments');

 

 


Quiz

1. 관련성을 가지며 중복이 없는 데이터들의 집합을 ( 데이터베이스)라고 한다.

2. ( PRIMARY KEY )는 기본 키로 로우를 대표하는 고유한 값을 의미

3. CRUD는 ( create ), ( read ), ( update ), ( delete )의 첫 글자를 모은 두 문자어

4. 특정 조건을 가진 데이터만 조회하기 위해 ( WHERE ) 절을 사용한다.

5. mysql 작업을 쉽게 할 수 있도록 도와주는 라이브러리는 ( 시퀄라이즈 )이다.

6. 1:N 관계를 표현하기 위해 속성 ( hasMany ), ( belongsTo )를 사용한다.

7. 관계 쿼리를 사용하기 전에 ( include ) 속성을 사용한다.

 


Programming Quiz

1. 밑에 나온 쿼리를 nodsjs로 나타내보시오.

select * from nodejs.users;

 

2. nodejs에서 SQL 쿼리를 써야 하는 경우, 빈칸을 채우시오.

 

const [result, metadata] = [                      ]('select * from comments');

Answer

1.

User.findAll({});

 

2.

const [result, metadata] = await sequelize.query('select * from comments');

 


출처 :  조현영,  Node.js 교과서 개정 3판, 길벗(2022)

Corner Node.js 1
Editor : Krong

728x90

관련글 더보기