NestJS TypeOrm 적용하기

이민택·2021년 2월 3일
14

NestJS

목록 보기
1/1

NestJS TypeOrm 연결

NestJS 는 여러 데이터 베이스를 적용할 수 있는데 TypeScript 와 호환성이 좋은 TypeOrm 을 적용하는 방법에 대해서 블로그를 남겨보겠다

테스트 MySQL 생성

MySQL 은 도커를 이용해서 생성해 준다 도커를 설치한 상태에서 아래 명령어를 입력하면 MySQL 8 버전을 도커 위에서 실행할 수 있다 ( charset은 utf-8을 사용하기 위해 설정 값을 넣어주었다)

docker run -d -p 3306:3306 --name typeorm-test-mysql -e MYSQL_ROOT_PASSWORD=1234 -d mysql:8 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

테스트 schema 생성

docker 로 생성한 mysql 에 접속한 다음 이름이 test인 schema를 작성해 준다

// 도커 컨테이너 접속
docker exec -it {컨테이너ID} bin/bash

//mysql 접속
mysql -u root -p

//test schema 생성
create schema test

테스트 프로젝트 생성

nestjs cli를 설치했다는 가정하에 아래 명령어를 이용해서 nestjs 프로젝트를 생성해 준다 설정에서 yarn 과 npm 중에서는 yarn 선택했다

//nestjs cli global module 설치
npm install -g @nestjs/cli

// nestjs 새로운 프로젝트 설치
nest new typeorm-test-project

TypeOrm 모듈 설치

nestjs 공식 문서에서 가이드 하는 @nestjs/typeorm, typeorm, mysql2 모듈을 설치한다

yarn add @nestjs/typeorm typeorm mysql2

TypeOrm 모듈 import

typeorm 에 연결하기 위해서는 App module에서 typeorm module을 import 해주면 된다 module을 import 할 때는 TypeOrm 모듈의 설정값이 동적이기 때문에 TypeOrm module을 forRoot 메소드를 이용해서 import 해준다

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: '1234',
      database: 'test',
      entities: [],
      synchronize: true, // false가 안전함
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

synchronize 기능을 키면 작성된 entity와 database간의 씽크를 맞춰준다 해당 기능을 사용하면 편할 수 있지만 원하지 않는 시점에 database구조가 달라질 수 있으므로 주의해야한다 그래서 entity 설정과 씽크를 맞춰주기 위해서 typeorm cli 를 이용해서 원하는 시점에 sync를 맞추는게 좋다

//entity와 sync를 맞춰줌
yarn typeorm schema:sync

Entity 정의

entity를 TypeOrm에 맵핑해주기 위해서는 entity의 위치를 설정 해줘야한다 우선 entity를 두개 정의해주겠다

nest g mo user
nest g mo order

각각 모듈 안에 entity 파일을 정의해 준다 user와 order가 1: n 구조를 가지는 단순한 구조이다

user.entity.ts

import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
import { Order } from '../order/order.entity';

@Entity('USER')
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({
    type: 'text',
    name: 'NAME',
  })
  name: string;

  @OneToMany(() => Order, (order) => order.user)
  orders: Order[];
}

order.entity.ts

import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
import { User } from '../user/user.entity';

@Entity('ORDER')
export class Order {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({
    type: 'int',
    name: 'PRICE',
  })
  price: number;

  @ManyToOne(() => User, (user) => user.orders)
  user: User;
}

각 entity를 정의해 주고 프로젝트를 실행하면 entity를 찾지 못한다는 오류가 나오게 된다 그래서 entity의 위치를 기본 설정에 추가해줘야한다 entity의 위치를 설정하는 방법은 여러가지 있지만 여기서는 path를 이용한 패턴을 사용했다

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: '1234',
      database: 'test',
      entities: [join(__dirname, '/**/*.entity.ts')],// 설정 부분
      synchronize: true,
    }),
    UserModule,
    OrderModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

위와 같이 기입하고 프로젝트를 실행하면 sychronize 가 켜져 있기 때문에 정의한 entity가 db에 생기는 것을 볼 수 있다

env 파일을 이용해서 TypeOrm config 설정하기

TypeOrm을 NestJS 와 연결하기 위해서 데이터 베이스의 호스트와 비밀번호 등 여러 보안 정보를 입력해야되기 때문에 이를 위해서 주로 env 파일을 이용한다 nestjs 에서는 이런 환경 변수 설정을 해주기 위해서 config 모듈을 지원한다 이 모듈을 설치하면 기존에 알고 있던 dotenv 모듈도 같이 설치 된다

yarn add @nestjs/config

이제 env 파일과 NestJS에서 config 설정을 해줄 파일을 아래와 같이 생성해 준다

  • .env

DATABASE_USER=root
DATABASE_PASSWORD=1234
DATABASE_PORT=3306
DATABASE_HOST=localhost
DATABASE_NAME=test
  • cofiguration.ts
import 'dotenv/config';
export default () => ({
  database: {
    host: process.env.DATABASE_HOST || '',
    user: process.env.DATABASE_USER || '',
    name: process.env.DATABASE_NAME || '',
    password: process.env.DATABASE_PASSWORD || '',
    port: process.env.DATABASE_PORT || '',
  },
});

위와 같이 설정하면 이제 App 모듈 내부에서 import 해주는 작업을 해줘야 한다 cofig 모듈을 import 할때 configuration 파일을 불러온다 이제 App 모듈 내부에서는 configService를 이용해서 환경변수에 접근할 수 있다

TypeOrm 모듈을 import 할 당시는 아직 CofigModule이 AppModule에 적용되기 전이기 때문에 아래와 같이 모듈 설정에서 import와 configServeice inject까지 해줘야 한다


@Module({
  imports: [
    ConfigModule.forRoot({   // configuration 설정을 coifg module 불러 올 때 로드한다
      isGlobal: true,
      load: [configuration],
    }),
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        type: 'mysql',
        host: configService.get('database.host'),
        port: configService.get('database.port'),
        username: configService.get('database.user'),
        password: configService.get('database.password'),
        database: configService.get('database.name'),
        entities: [join(__dirname, '/**/*.entity.js')],
        synchronize: true,
      }),
    }),
    UserModule,
    OrderModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
profile
데이터에 소외된 계층을 위해 일을 하는 개발자를 꿈꾸는 학생입니다

0개의 댓글