[게시판 만들기] TIL 3. join 라우터 및 DB


  1. 라우터 분리
  2. Sequelize
  3. Join API 3.1. controllers 3.2. middlewares


😀 Notice Board 레파지토리😀
Stack : Javascript, express, nodejs, sequelize


★ : 이번 과정을 통해서 새로 만들어진 파일

☆ : 이번 과정을 통해서 수정된 파일

/
├── 📁/server
│   ├── 📄README.md                     # Notice_Board README.md 파일
│   ├── 📄index.js                      # node.js로 작성된 웹 서버 진입점
│   ├── 📄☆ package.json
│   ├── 📄☆ package-lock.json
│   ├── 📄.gitignore                    # node_modules, env 등 포함되지 않게 설정요망
│   ├── 📁/config                       # 환경설정
│   │    └── 📄★ config.js                        
│   ├── 📁/migrations                 
│   │    ├── 📄★ 20210819052749-create-users.js
│   │    └── 📄★ 20210819065842-add-column-in-usersTable.js          
│   ├── 📁/models                       # DB 모델 파일
│   │    ├── 📄★ index.js              
│   │    └── 📄★ users.js               
│   ├── 📁/routes
│        └── 📄★ index.js              # 분기 파일
│   


1. 라우터 분리

공식 레퍼런스 👉 https://expressjs.com/en/4x/api.html#router

/routes/index.js

const express = require('express');
const router = express.Router();

const { userController } = require('../controllers');


router.get('/', (req, res) => {
  res.send("Site access success");
});

router.post('/user/join', userController.join.post);

module.exports = router;

프로젝트를 하다보면 기능이 많아지고, 코드양이 너무 많이 늘어나 유지보수가 힘들진다. 이것을 쉽게 하기 위해서는 연관이 있는 라우터끼리 분리해 관리하기도 한다. (Express를 사용하는 이ㅠ기도 한다.)

1.1 express.Router()

const express = require('express');
const router = express.Router();

const router = express.Router();는 새 라우터 객체를 만드는 코드이다. 매개변수로 들어갈 수 있는 옵션이 총 3개가 있다.

caseSensitive를 매개변수로 넣으면 대소문자 구분을 한다. 라우터는 기본적으로 “/Foo”와 “/foo”를 통일하게 인식한다. mergeParams를 넣으면 상위 라이터의 req.params값을 유지한다. 만약 상위와 하위의 매개변수 이름이 충돌하게 되면 하위 값을 우선시한다.strict는 라이팅의 기준이 엄격해진다. 엄격이라 함은, 라우터는 기본적으로 “/foo”와 “/foo/”를 동일하게 인식하는데, 이런 부분을 말한다.

여하튼 router라는 라이터 객체를 만들어놨으니, 이제 router로 라우터의 기능을 사용할 수 있다.

module.exports = router;

그리고 이렇게 만들어진 라우터를 마지막 줄에 위 코드를 추가함으로써 모듈로 만든다.

1.2 app.METHOD(경로, 콜백 [, 콜백 …])

router.get('/', (req, res) => {
  res.send("Site access success");
});

router.post('/user/join', userController.join.post);

app.METHOD에는 해당하는 GET, PUT, POST, DELECT 등은 HTTP 요청 메소드이다. 이 메소드는 모두 소문자로 되어있다. 짧게 설명하면 GET은 고객이 요청한 정보를 검색하여 응답하는 것이고 PUT은 요청된 데이터를 DB에서 수정하는 메소드이다. POST는 요청된 데이터를 DB에 새로 생성한다. DELETE 는 데이터를 삭제한다. 위 코드에선 join이 고객에게 받은 회원가입 정보를 데이터베이스에 집어 넣는 것이기 때문에post요청만을 했다.

물론 실제로 요청을 보낸다고 해서 무조건 이루어지는 것이 아니다. 요청을 검증 후 유효할 때만 실행된다.

1.3 app.use();

/index.js

const express = require('express');

require("./models");
const Route = require("./routes/index");


const app = express();
const port = 3000;


app.use(express.json());
app.listen(port, () => {
  console.log(`http://localhost:${port} port success`);
});

app.use(Route);


module.exports = app; 

이렇게 작성된 라우터는 미들웨어처럼 동작하기 때문에 app.use()나 또다른 라우터의 use() 메소드에 해한 인수로 사용한다.

...
const Route = require("./routes/index");
...
app.use(Route);

기본 경로에 있는 index.js를 보면 위 두 줄이 추가된 것을 볼 수 있다.

const Route = require("./routes/index");

위 코드는 모듈화된 라우터 객체를 사용하도록 불러온 것이고,

app.use(Route);

위 코드는 불러온 라우터 객체를 사용자의 요청에 맞게 사용하기 위해 존재하는 코드이다.



2. Sequelize

공식레퍼런스👉 https://sequelize.org/master/manual/migrations.html#the-cli

npm i sequelize

2.1 Sequelize-cli

2.1.1 ORM(Object-Relational-Management)

Sequelize를 공부하기 전에 먼저 알아야 할 것은 ORM이라는 개념이다. ORM은 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑해, DB의 기능을 사용하게 하는 것이다. ORM이 없었다면 쿼리 작성을 통해서 테이블 생성, 조회, 업데이트, 외래키설정을 했어야 했다.

쿼리를 사용하는 것보다 기능이 떨어지지만, 쿼리를 신경쓰지 않아도 되며, 마이그레이션을 쉽게할 수 있다는 장점이 있다.

2.1.2 Sequelize-Cli

nodejs에는 다양한 ORM이 존재하는데, Sequelize 가 그 중 하나이다. 데이터베이스 변경사항을 관리하기 위해서는 npm i sequelize를 하여 Sequelize를 설치 하는 것만으로는 안된다. 마이그레이션이라는 것을 사용해야한다. (마이그레이션이란, 다른 운영환경으로 옮겨가는 과정을 말하는데, 데이터를 한 위치에서 다른 위치로, 또는 한 형식에서 다른 형식으로 이동하는 프로세스를 말한다.)

Sequelize 에서 이러한 마이그레이션을 하기 위해서는 Sequelize-cil가 필요하다. 이는 The Sequelize command line interface의 줄임말로, 명령어를 통해 데이터베이스 작업을 할 수 있는 툴이다. 기능으로는 마이그레이션, 시드, 모델이 있다.

▶ CLI 설치

npm install --save-dev sequelize-cli

▶ 빈 프로젝트 생성

npx sequelize-cli init

위 명령어를 입력해주면 cofing, moderls, migrations, seeders 폴더가 생성된다.

2.2 cofing

cofing 파일은 CLI가 데이터베이스와 연결하기 위해 존재한다. dotenv를 사용함으로, .env에서 끌고올 내용이 있어서 js파일로 바꿨지만, 원래대로라면 josn 파일이 맞다.

/config/config.js

require("dotenv").config();

module.exports= {
  "development": {
    "username": process.env.DATABASE_USERNAME,
    "password": process.env.DATABASE_PASSWORD,
    "database": process.env.DATABASE_NAME,
    "host": process.env.DATABASE_HOST,
    "dialect": "mysql"
  },
  "test": {
    "username": process.env.DATABASE_USERNAME,
    "password": process.env.DATABASE_PASSWORD,
    "database": process.env.DATABASE_NAME,
    "host": process.env.DATABASE_HOST,
    "dialect": "mysql"
  },
  "production": {
    "username": process.env.DATABASE_USERNAME,
    "password": process.env.DATABASE_PASSWORD,
    "database": process.env.DATABASE_NAME,
    "host": process.env.DATABASE_HOST,
    "dialect": "mysql"
  }
}

dotenv 라이브러리는 라이브러리를 임포트 한 후, config()를 호출해주기만 하면 된다. 그리고 process.env로부터 .env에 있는 환경변수를 읽고 출력한다.

2.3 models,migrations 파일 만들기

npx sequelize-cli model:generate --name User --attributes nickname:string,email:string,password:string

moderls파일과 migrations 파일을 만들기 위해서는 위와 같은 명령어를 사용하면 된다.

npx sequelize-cli db:migrate

작성한 모델은 우와 같은 명령어로 마이그레이션을 할 수 있다. 바로 직전에 한 마이그레이션 취소는 npx sequelize-cli db:migrate:undo로 할 수 있다. 모든 마이그레이션 취소는 npx sequelize-cli db:migrate:undo:all를 통해 할 수 있다.

| Field     | Type         | Null |   Key   | Default | Extra          |
| --------- | ------------ | ---- | ------- | ------- | -------------- |
| id        | int          | NO   | PRI, FK | NULL    | auto_increment |
| nickname  | varchar(255) | NO   |         | NULL    |                |
| email     | varchar(255) | NO   |         | NULL    |                |
| password  | varchar(255) | NO   |         | NULL    |                |
| createdAt | datetime     | NO   |         | NULL    |                |
| updatedAt | datetime     | NO   |         | NULL    |                |

마이그레이션을 마치고 나면 위와 같은 테이블이 완성됐을 것이다.

2.4 칼럼추가

join API를 작성할 때, 비밀번호를 단방향 암호화하여 테이블에 저장하는 작업을 해야해서 스캘레톤을 사용했다.**

npx sequelize migration:create --name add-column-in-usersTable

생성된 마이그레이션 파일에는 아래처럼 적어주면 된다.

/migrations/20210819065842-add-column-in-usersTable.js

'use strict';

module.exports = {
  up: async (queryInterface, Sequelize) => {
    queryInterface .addColumn( 'Users', 'salt', Sequelize.STRING )
  },

  down: async (queryInterface, Sequelize) => {
    await queryInterface.removeColumn('Users', 'salt');
  }
};

문제는 위 작업까지만 하면, 우리의 DB에는 반영이되지만, Javascript로 접근하여 사용할 수 없다.

/models/users.js

'use strict';
const {
  Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
  class Users extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      // define association here
    }
  };
  Users.init({
    nickname: DataTypes.STRING,
    email: DataTypes.STRING,
    password: DataTypes.STRING,
    salt: DataTypes.STRING // 추가
  }, {
    sequelize,
    modelName: 'Users',
  });
  return Users;
};

위 코드처럼 추가하고자 하는 칼럼을 모델 파일에 추가해줘야 한다.




© 2020. by RIVER

Powered by RIVER