Posts 노드 스터디 7장
Post
Cancel

노드 스터디 7장

MySQL

데이터베이스란

  • DBMS : 데이터베이스 관리시스템
  • RDBMS : 관계형 DBMS. 대표적으로 Oracle, mysql, mssql 등이 있음.

Datagrip 사용

  • Datagrip : 데이터베이스를 위한 IDE. 학생인증을 하면 무료사용가능
  1. 프로젝트 생성
  2. alt+insert 혹은 좌측 + 클릭 -> 원하는 데이터베이스 클릭
  3. 좌측 하단에 download 클릭
  4. 이후 유저이름, 비밀번호 생성 후 ok
  5. 좌측 상단 초록 화살표 클릭하여 connect
  • 오류
    • 내용 : Server returns invalid timezone. Need to set ‘serverTimezone’ property.
    • database의 property의 들어가서 advanced 탭을 클릭한 후, serverTimezone 의 값을 Asia/Seoul 로 변경한다.

데이터베이스 및 테이블 생성

  • 교재에서는 프롬프트로 진행
  • 데이터 베이스 생성 : CREATE SCHEMA [데이터베이스명]

    • 옵션 : DEFAULT CHARACTER SET utf8 -> utf8 셋을 사용하여 한글을 사용할 수 있게함.
    • SCHEMA 대신 DATABASE를 사용해도 됨.
    • Mysql에선 SCHEMA 와 DATABASE는 같은 말
  • 테이블 생성
1
2
3
4
5
6
7
8
9
10
11
12
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 CHARACTER SET = utf8
  -> ENGINE = InnoDB;
  • CREATE TABLE nodejs.users : 명령어 + 테이블 명. 이때 테이블 명은, 데이터베이스명.테이블명 으로 함.
    • use nodejs; 로 이 데이터베이스에 들어왔떈 데이터베이스명 생략가능.
  • 컬럼 선언 : () 안에 선언함. [컬럼명 자료형 옵션] 으로 구성

    • ex : id INT NOT NULL AUTO_INCREMENT

    • 자료형

      • INT / FLOAT / DOUBLE : 숫자
      • VARCHAR(자릿수) / CHAR(자릿수) : 문자열 저장
        • VARCHAR 은 가변길이로, 20이면 0~20까지 저장가능하지만, CHAR은 반드시 20을 채워야함.
      • TEXT : 긴 글을 저장할 때 사용. 수백자 이내면 VARCHAR로 처리하고, 이상이면 TEXT로 처리
      • TINYINT : -128 ~ 127 까지의 정수를 저장. 0과 1만 저장하면 BOOLEAN으로 활용 가능.
      • DATETIME : 날짜와 시간에 대한 정보를 담고 있음.
      • 이 외 많은 자료형들이 있지만 위에가 자주 사용하는 것들.
    • 옵션

      • NULL / NOT NULL : 빈칸을 허용할지 안할지.
      • AUTO_INCREMENT : 숫자를 자동으로 올림.
      • UNSIGNED : 숫자 자료형일때 사용가능. 음수를 무시하고 양수를 더 크게 받을 수 있음.
      • ZEROFILL : 숫자의 자릿수가 고정되어있을 때, 앞을 0으로 채움.
        • ex) INT(4) 인데 1을 넣으면 0001로 저장.
      • DEFAULT : 데이터베이스 저장시 해당 컬럼에 값이 없으면 MySQL이 기본 값을 대신 넣음.
        • 위에선 now()를 사용해서, 저장할 당시의 시간을 저장
        • now() 대신에 CURRENT_TIMESTAMP 를 사용해도 됨.
      • PRIMARY KEY : row를 대표하는 기본키일 경우 설정.
        • 컬럼을 다 적고, 위에서처럼 따로 적어도 된다.
      • UNIQUE INDEX : 값이 고유해야하는지 묻는 옵션. PRIMARY KEY는 자동으로 설정됨.
      • CONSTRAINT [제약조건명] FOREIGN KEY [컬럼] REFERENCES [참고하는 테이블명] [참고하는 컬럼명]
        • 외래키. 서로 연결하는 것.
        • ON UPDATE / DELETE : 연결한 것이 수정되거나 삭제될 시 하는 행위 정의
          • CASCADE로 하면 같이 수정하거나 삭제함.
    • 테이블 자체 옵션

      • 테이블 컬럼 작성이 끝나고 이후에 옵션으로 붙임.
      • COMMENT : 테이블에 대한 보출 설명
      • DEFAULT CHARACTER SET : utf8으로 설정하지 않으면 한글입력이 안됨.
      • ENGNED : MylSAM과 InnoDB를 제일 많이 사용함.
  • 테이블 확인 : desc [테이블명]
  • 테이블 제거 : drop table [테이블명]

CRUD 작업하기

  • Create : 그냥 데이터를 넣는 것.

    • insert into [테이블명] (컬럼, 컬럼) VALUES (값, 값);
  • read : SELECT (컬럼, 컬럼) FROM [테이블명]

    • 모든 컬럼을 조회하려면 * 사용
    • WHERE 로 특정 조건을 가진 데이터만 조회가능
      • EX) WHERE married = 1 AND age > 30;
    • ORDER BY [컬럼명] [ASCDESC]
      • 정렬 기능.
    • LIMIT [숫자]
      • 조회할 로우 개수 설정.
    • OFFSET [건널뛸 숫자]
      • 처음부터 몇개까지 건널 뛰고 출력할 건지 정할 수 있음.
      • 반드시 LIMIT 과 함께 쓰여야함.
  • Update : UPDATE [테이블명] SET [컬럼명=바꿀값] WHRER [조건]

    • 조건에 맞는 row의 해당하는 column을 수정할 수 있음.
  • Delete : DELETE FROM [테이블명] WHERE [조건]

    • 조건에 맞는 row를 삭제

시퀄라이즈 사용

  • ORM : 자바스크립트 객체와 데티어베이스의 관계를 매핑해주는 도구.
  • MySQL외 다른 MariaDB, PostgreSQL, SQLite, MSSQL 등 다른 데이터베이스도 같이 쓸 수 있음.
  • 자바스크립트 구문을 알아서 SQL로 바꿔줌. 따라서 SQL 언어를 직접 사용하지 않아도 자바스크립트 만으로 MySQL을 조작할 수 있고, 다룰 수 있음.

설치 후 초기화

  • 설치 : sequelize, sequelize-cli, mysql2

    • sequelize :
    • sequelize-cli : 시퀄라이즈 명령어를 실행하기 위한 패키지
    • mysql2 : mysql과 시퀄라이즈를 이어주는 드라이버
  • 설치 후 sequelize init 명령어로 초기화 -> config, models, migrations, seeders 폴더 생성

    • models/index.js에서 sequelize cli 가 자동으로 생성해주는 코드는 필요없는 부분이 많음. 따라서 다음처럼 정리 가능
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 연결

  • 시퀄라이즈 연결
1
2
3
4
5
6
7
8
9
10
11
const { sequelize } = require("./models");
...
sequelize
   .sync({ force: false })    // 서버 실행 시 mysql 연결. force:true 일 경우, 서버 실행 시 마다 테이블을 재생성함. 테이블을 잘못만든 경우 true로 설정
   .then(() => {
      console.log("데이터베이스 연결 성공");
   })
   .catch((err) => {
      console.error(err);
   });

  • MySQL과 연동할 땐, config 폴더 안의 config.json 정보가 사용됨.
    • operatorAliases가 있다면 삭제.
    • 나머지는 적절히 수정

모델 정의하기

  • 시퀄라이즈 모델 == MySQL 테이블
  • 시퀄라이즈는 모델과 MySQL 테이블을 연결해주는 역할을 함.
  • 보통 모델 이름은 단수형으로, 테이블이름은 복수형으로 함.
  • 모델 함수

    • static init
      • 테이블에 대한 설정을 함.
    • static associate
      • 다른 모델과의 관계를 적음.
  • 자료형 대응
MySQL시퀄라이즈
VARCHAR(100)STRING(100)
INTINTEGER
TINYINTBOOLEAN
DATETIMEDATE
INT UNSIGNEDINTEGER.UNSIGNED
NOT NULLallowNull: false
UNIQUEunique: true
DEFAULT now()defaultValue: Sequelize.NOW
  • 자세한 모델 정의/연결법은 강의에서 찾아보기 [https://thebook.io/080229/ch07/06/02-04/]

관계정의하기

  • 1:N - 시퀄라이즈에선 hasMany 라는 메서드로 표현됨.
    • belongsTo : 로우를 불러올대 연결된 테이브르이 로우를 가져오도록 함.
    • 어디에 belongsTo를 쓰는가 -> 다른 모델의 정보가 들어가는 테이블에 쓰면 됨.
    • hasMany에서는 sourceKey를 쓰고, belongsTo에서는 targetKey를 사용
  • 1:1 - hasOne 사용
  • N:M - belongsToMany
    • 양쪽에서 belongsToMany로 연결해주면 됨.
    • through 속성에 넣은 이름으로 새로운 모델을 만들어냄.

쿼리 알아보기

  • 쿼리는 프로미스를 반환하므로 then을 붙여서 결괏값을 받을 수 있다.
  • 대응

    • 주의점 : MySQL의 자료형이 아니라, 시퀄라이즈 모델에서 정의한 자료형대로 넣어야함. 시퀄라이즈가 자동으로 변경함.
  • 조회
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
SELECT * FROM nodejs.users;
User.findAll({});

SELECT * FROM nodejs.users LIMIT 1;
User.findOne({});

SELECT name, married FROM nodejs.users;
User.findAll({
  attributes: ['name', 'married'],
});

SELECT name, age FROM nodejs.users WHERE married = 1 AND age > 30;
const { Op } = require('sequelize');
const { User } = require('../models');
User.findAll({
  attributes: ['name', 'age'],
  where: {
    married: 1,
    age: { [Op.gt]: 30 },   // 시퀄라이즈는 자바스크립트 객체를 사용하여 쿼리를 생성하므로, 특수 연산자 사용. Op.gt 은 operator greater than 임.
  },
});

//Op.or 사용
SELECT id, name FROM users WHERE married = 0 OR age > 30;
const { Op } = require('sequelize');
const { User } = require('../models');
User.findAll({
  attributes: ['id', 'name'],
  where: {
    [Op.or]: [{ married: 0 }, { age: { [Op.gt]: 30 } }],
  },
});

//Order by
SELECT id, name FROM users ORDER BY age DESC;
User.findAll({
  attributes: ['id', 'name'],
  order: [['age', 'DESC']],
});

SELECT id, name FROM users ORDER BY age DESC LIMIT 1;
User.findAll({
  attributes: ['id', 'name'],
  order: [['age', 'DESC']],
  limit: 1,
});

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,
});
  • 수정 : 첫번째로 수정할 내용, 두번째로 조건
1
2
3
4
5
6
UPDATE nodejs.users SET comment = '바꿀 내용' WHERE id = 2;
User.update({
  comment: '바꿀 내용',
}, {
  where: { id: 2 },
});
  • 생성
1
2
3
4
5
6
7
8
9
10
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',
});

  • 삭제
1
2
3
4
DELETE FROM nodejs.users WHERE id = 2;
User.destory({
  where: { id: 2 },
});

관계쿼리

  • 관계쿼리 : find 메소드에서 옵션으로 include를 주면, JOIN 메소드 사용가능.
1
2
3
4
5
6
7
8
// 특정사용자를 가져오면서, 댓글까지 모두 가져오고 싶을때
const user = await User.findOne({
  include: [
    {
      model: Comment,
    },
  ],
});
  • 여기서 user.Comments로 접근 가능.
  • 관계를 설정했다면, 아래 메소드 지원
    • getComments, setComments, addComment, addComments, removeComments
    • 이렇게, 동사뒤에 모델의 이름을 붙여서 사용한다.
    • 동사 뒤에 모델 이름을 바꾸고 싶으면, 관계 설정시 as 옵션을 사용할 수 있음.
1
2
3
4
5
db.User.hasMany(db.Comment, {
  foreignKey: "commenter",
  sourceKey: "id",
  as: "Answers",
});
  • include 나 관계 쿼리 메소드에도 where나 attributes 같은 옵션을 사용할 수 있음.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const user = await User.findOne({
  include: [
    {
      model: Comment,
      where: {
        id: 1,
      },
      attributes: ["id"],
    },
  ],
});
// 또는
const comments = await user.getComments({
  where: {
    id: 1,
  },
  attributes: ["id"],
});
  • 관계쿼리 수정, 생성, 삭제 때는 조금 다르게 함.
1
2
3
4
const user = await User.findOne({});
const comment1 = await Comment.create();
const comment2 = await Comment.create();
await user.addComment([comment1, comment2]);

SQL 쿼리하기

  • 직접 SQL 쿼리를 사용할 수 있음.
1
2
const [result, metadata] = await sequelize.query("SELECT * from comments");
console.log(result);
This post is licensed under CC BY 4.0 by the author.

노드 스터디 6장

REACT/CORS 개발 환경에서, 외부 API 와 연결할때 쿠키가 생성되지 않는 문제

Comments powered by Disqus.