57일차 (03-02-2021)

조상래·2021년 3월 2일
0

코드스테이츠

목록 보기
55/73

우린 mysql 모듈을 이용하여 데이터베이스에 대해 요청을 할 때 쿼리문을 작성하여야했다. 쿼리문... 꽤나 직관적이지만 길기도하고, 긴만큼 정확성이 떨어진다. 그리고 쿼리문에 익숙하지 못한 사람이 노드환경에서 데이터베이스를 이용하기란 조금 힘들 것이다.

이러한 상황에서 대체할 수 있는 모듈이 있다. 그건 바로 Sequelize이다. 이 모듈은 쿼리문보다 코드 작성에 익숙한 사람에게 정말 유용한 모듈이다.

쿼리문 만큼 직관적이고, 또 더욱 단순한 모양으로 쿼리문을 대체할 수 있다. 그리고 Sequelize를 더욱 편하게 이용하기 위한 툴이 있다. Sequelize-cli라는 툴로 마이그레이션(이주/migration으로 스키마 변경에 따른 데이터 이주를 뜻한다.) 를 쉽게 도와준다.

이를 이용해 직접 데이터베이스를 구축해보자.

1. 사전준비

아무 디렉토리를 하나 잡고 시작하면 된다. npm init으로 package.json 파일을 만들어 주자.

그리고 Sequelize와 Sequelize-cli를 설치해보자.

$ npm install sequelize
$ npm install sequelize-cli

cli를 통해 필요한 기본적인 파일들을 쉽게 설치할 수 있다.

$ npx sequelize-cli init

위 명령어를 쓰면 작업할 디렉토리안에 config, migrations, models, seeders 디렉토리가 생기는 것을 볼 수 있다.

그리고 mysql에 연습할 데이터베이스 하나를 만들자. 나는 testDB로 만들었다.

2. 연결설정

config/config.json 파일을 들여다보자.

{
  "development": {
    "username": "root",
    "password": null,
    "database": "database_development",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "production": {
    "username": "root",
    "password": null,
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "mysql"
  }
}

위와같은 제이슨 형태의 데이터를 볼 수 있는데, 위 객체안의 속성 세가지 development, test, production 이 보인다. 상황에 맞게 사용하면 되는데 models/index.js 파일을보면 환경변수를 따로 지정해주지 않을시 기본적으로 development로 진행이 되는 것을 볼 수 있다.

자신의 정보를 알맞게 넣어주자.

3. 모델/ 마이그레이션

모델이란 스키마와 같다. 예전에는 sequelize를 이용하여 직접 코드를 하나하나 다 작성했어야하지만, cli로 손쉽게 작성이 가능하다.

그 전에 먼저 models/index.js 파일에 대해 설명하자면, connection의 역할을 할 뿐만 아니라. db라는 객체안에 모델들을 속성으로 넣어 관리할 수 있게 해준다. 방식은 models 디렉토리 안의 다른 model 파일들을 하나하나씩 읽어 기억하는 것이다.

그럼 이제 모델을 하나 만들어보자. 간단하게 test라는 모델을 만들어 보겠다.

$ npx sequelize-cli model:generate --name test --attributes name:string,age:integer

위 명령어로 아주 간단하고 직관적으로 모델을 만들수 있다. --name 옆엔 모델이름 --attribute안에 컬럼과 데이터 타입(integer=> int, string=> varchar(255))을 명시해주면 된다. 위 명령어를 실행하면 두가지의 파일이 생긴다 migrations/2021xxxxxx-create-test.js, models/test.js. 먼저 두 파일의 내용을 보면 비슷한 모습을 하고있다.

그러나 models의 파일은 mysql을 이용할 때 계속 사용되어 지는것이고 migrations의 파일은 테이블을 생성할 때 한번 사용되어진다. 쉽게말해 migrations의 역할은 테이블의 겉 모습을 만드는 것일 뿐 데이터베이스의 참조나 업데이트 등은 실질적으로 models에서 일어 나는 것이다. 그리고 모델을 생성하면 자동으로 마이그레이션 안에 복수형(tests)로 들어간다. 이것은 테이블 이름이된다.

migrations 파일이 굳이 필요 없는 것처럼 보이지만, 기록을 남기고 명령어를 이용하여 변화를 줬던 데이터를 다시 전 상태로 되돌릴 수 있는 아주 유용한 역할을 한다.

다음은 이렇게 만들어진 스키마를 migrate 해보자.

$ npx sequelize-cli db:migrate

(위 명령어를 실행하기 전 mysql2 모듈의 설치가 선행될 것이다.)

그리고 직접 데이터베이스를 확인해 보면 테이블이 추가 되어있을 것이다. 참고로 SequelizeMeta는 마이그레이션을 기록하는 테이블이다.

만약 이 과정에서 실수가 있었다면,

$npx sequelize-cli db:migrate:undo

위 명령어를 쓰면 전 상태로 되돌릴 수 있다.

4. 서버를 이용한 데이터 추가 및 조회.

이 과정을 하기 위해선 서버에 대한 이해가 아주 조금만 있으면 된다. 먼저 나는 express를 이용해 간단한 서버를 하나 구축하였다.

const express = require('express');
const app = express();
const port = 3000;
const db = require('./models');
const jsonParser = require('body-parser'); // json형식을 변환하는 미들웨어.
const test = db.test

app.use(jsonParser.json());
app.post('/test', (req, res) => {
  const {name, age} = req.body;
  test.create({name: name, age: age})
  .then(data => {
    res.status(201).send(data);
  })
  .catch(err => {res.status(400).send('bad-request')})
})

위에서 말했듯이 db는 모든 모델을 객체화 해서 관리한다고 했다. 그래서 임의로 콘솔로그를 찍어보면 객체안에 모델이 들어가 있는것을 직접 확인이 가능하다. 그리고 create 메소드를 이용해 INSERT INTO와 같은 기능을 구현할 수 있다.

포스트맨을 이용해 보내보면,


잘 등록이 된 모습을 볼 수 있다. 참고로 메소드는 promise로 반환하여 비동기 동작에도 유연하다.

// 생략
app.get('/test/:id', async (req, res) => {
  const id = req.params.id;
  try {
    const data = await test.findAll({where: {id: id}});
    if (data.length === 0) {
      throw new Error()
    }
    res.status(200).send(data);
  } catch (e) {
    res.status(404).send('NOT FOUND!');
  }
})

프로미스를 반환하는 점에서 async/awiat를 이용해 볼수도 있다. 주목할 점, findAll은 SELECT FROM 명령어와 같은 역할 을 한다. 안의 인자로 객체를 이용하여 조건을 만들수 있으며, 비우면 모두 조회가 된다.

공식문서에 설명이 잘 되어있기에 참고하는게 좋다.

요번 스프린트는 공식문서 파해치기였다. 코드스테이츠에서 제공 하는 정보는 심하게 적었다... 뭔가 모험을 하는 기분이 들었다. 저기 db객체를 알고 이용하기 까지 3시간 정도를 소모했다. 이것 저것 콘솔을 다 찍어보기도 하고, 검색을 해보기도 하였으며, 말도 안된다 생각이 드는 코드도 적었었다. 그러다 보니 슬슬 해답이 나왔다.

테스트는 무사히 다 통과하였지만, 과연 이게 맞나? 싶은 느낌은 지울수가 없다. 그래도 나의 문제해결 능력이 많이 늘었단 걸 몸소 느꼈다.

이번 스프린트에서 참 많이 얻은 것 같다. express의 라우터 사용까지 익숙해졌다. 코드스테이츠 최고!

profile
Codestates Full IM26기 수료

0개의 댓글