[Nest] Nest 시작하기 (2) - DB연결 ( mysql, sequelize)

권준혁·2021년 1월 3일
0

nest

목록 보기
2/2
post-thumbnail
post-custom-banner

Nest로 만든 백엔드 서버를 mysql DB와 연결해보자.

Nest 공식 깃허브주소 여기에 sample폴더에는 다양한 샘플코드가 있다. 07 sequelize에서 sequelize를 사용하는 코드를 따라 작성해본다.

git clone https://github.com/nestjs/nest.git

먼저 nest new 명령어를 이용해서 프로젝트를 만들고나면 생성되는 package.json과 샘플코드에서의 package.json을 비교해본다.

샘플코드처럼 작성해보기 위해 추가로 필요한 외부모듈들이다.

  • @nestjs/sequelize - nest전용 sequelize모듈
  • mysql2 - mysql 드라이버
  • sequelize - 프로미스 기반 Nodejs ORM
  • sequelize-typescript - 선언적 정의를 위한 데코레이터 세트 제공
  • @types/sequelize - sequelize에 대한 typescript정의

설치

필요한 모듈들을 설치해준다.

yarn add @nestjs/sequelize mysql2 sequelize sequelize-typescript @types/sequelize

의존성주입

AppModuleSequelizeModule 종속성을 주입하자.

import { Module } from '@nestjs/common';
import { SequelizeModule } from '@nestjs/sequelize';
import { AppController } from './app.controller';
// import { BoardModule } from './board/board.module';

@Module({
  imports: [
    SequelizeModule.forRoot({
      dialect: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: '1234',
      database: 'nest-board',
      models: [],
    }),
  ],
  controllers: [AppController],
})
export class AppModule {}

forRoot()메서드는 Sequelize생성자의 속성들을 모두 지원한다.
그리고 추가로 아래 사진의 속성들도 지원한다.

  • forRoot() 메서드가 추가로 지원하는 속성

여기까지 작성했다면, Sequelize객체를 AppModule 루트모듈에 의존성주입했기 때문에, 다른 모듈들에서는 import로 의존성 주입할 필요 없이 바로 가져다 사용할 수 있다.


모델

모델을 정의할 때, 데코레이터를 이용해 선언적인 형태로 작성한다.
아까 설치한 sequelize-typescript를 패키지를 이용한다.
다양한 데코레이터 사용 법 링크에서 자세히 볼 수 있다.
Advanced Example 데코레이터

각 데코레이터들을 간단하게 살펴본다.


Table

sequelizedefine options을 모두 사용할 수 있다.


Primary Key

id는 기본클래스에서 상속된다. 기본적으로 INTEGER타입이고 autoIncrement=true다. 기본적으로 sequelize에서와 동일하다. @Column({primaryKey: true})를 사용하거나 @PrimaryKey 와 @Column 데코레이터를 같이 사용해서 Override할 수 있다.


CreatedAt, UpdatedAt, DeletedAt

sequelize에서는 모델 생성 옵션에서 timestamps : true로 할 경우 자동으로 createdAt, updatedAt을 추가해줬다. Sequelize를 이용해 생성한거나 업데이트 할 때 자동으로 설정되는 필드다.
deletedAtparanoid: true(timestamps: true 해줘야 함)`할 경우, 생성 됐었다.

아래 사진을 보면 반대로 생각해 볼 수 있다. 어노테이션을 사용할 경우 option이 설정된다.


Column

파라미터 없이 간단히 사용할 수도 있다.

이 경우 타입추론이 가능해야 한다.

타입추론을 사용할 수 없거나 하지 말아야 할 경우에는 아래와 같이 사용한다.

import {DataType} from 'sequelize-typescript';

@Column(DataType.TEXT)
name: string;
@Column({
  type: DataType.Float,
  comment: "Some value",
  ...
})
  value: number;

아래 사진은 @Column 데코레이터와 함께 사용할 수 있는 데코레이터들이다.

다시 본론으로 돌아가서 Model을 작성해본다.


// board.model.ts
import {
  Column,
  DataType,
  Model,
  PrimaryKey,
  Table,
} from 'sequelize-typescript';

@Table({ timestamps: true, paranoid: true })
export class Board extends Model<Board> {
  @Column
  @PrimaryKey
  id: number;

  @Column
  author: string;

  @Column(DataType.TEXT)
  context: string;
}

모델을 작성했으면 SequelizeModule.forRoot의 models속성 배열에 넣어 Sequelize가 정상적으로 Model객체를 이용할 수 있게 해준다.

import { Module } from '@nestjs/common';
import { SequelizeModule } from '@nestjs/sequelize';
import { AppController } from './app.controller';
import { Board } from './board/board.model';

@Module({
  imports: [
    SequelizeModule.forRoot({
      dialect: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: '1234',
      database: 'nest-board',
      models: [Board],
    }),
  ],
  controllers: [AppController],
})
export class AppModule {}

그리고 Board스코프 내에서 BoardModel을 사용할 수 있도록 해줘야 한다.

import { Module } from '@nestjs/common';
import { SequelizeModule } from '@nestjs/sequelize';
import { BoardController } from './board.controller';
import { BoardService } from './board.service';
import { Board } from './board.model';

@Module({
  imports: [SequelizeModule.forFeature([Board])],
  controllers: [BoardController],
  providers: [BoardService],
})
export class BoardModule {}

다음은 서비스에서 Model객체를 직접 사용해보자

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/sequelize';
import { Board } from './board.model';

@Injectable()
export class BoardService {
  constructor(
    @InjectModel(Board)
    private boardModel: typeof Board,
  ) {}

  async getList(): Promise<Board[]> {
    return this.boardModel.findAll();
  }
}

이제 서비스에서 DB를 사용할 준비가 끝났다.


Model 자동로드

SequelizeModule.forRoot()에서 model속성의 배열에 하드코딩으로 model들을 추가하는 것이 귀찮거나, 애플리케이션 구현 구조가 유출되는게 싫다거나 (import 경로에 의해)한다면 아래 사진처럼 설정한다.

이 옵션을 지정하면 forFeature()를 통해 등록된 모든 모델이 배열에 자동으로 추가된다.
반대로 forFeature()를 통해 등록되지 않은 경우 등록되지 않으니 이 옵션을 사용하면 안된다.


@nestjs/sequelize 보다는 @nestjs/typeorm 이 훨씬 더 많이 사용된다.
다음 nestjs 포스팅에서는 typeorm에 대해 자세히 알아봐야겠다.

profile
웹 프론트엔드, RN앱 개발자입니다.
post-custom-banner

0개의 댓글