TypeORM & Configuring

๊น€๋ฏผ์žฌยท2021๋…„ 11์›” 27์ผ
2

Nest.JS & graphQl

๋ชฉ๋ก ๋ณด๊ธฐ
3/7

*๐Ÿ”Study Keyword :

๐Ÿ”‘TypeORM & ๐Ÿ”‘Configuring์„ ํ†ตํ•ด TypeORM์„ ๋“ฑ๋กํ•ด๋ณด์ž

ORM์ด๋ž€?

๊ฐ์ฒด์™€ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ๋ณ€ํ˜• ๋ฐ ์—ฐ๊ฒฐํ•˜๋Š” ์ž‘์—…์œผ๋กœ orm์„ ํ™œ์šฉํ•˜๋ฉด ๊ฐœ๋ฐœ์€ ๊ฐ์ฒด์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ณ€ํ˜•์— ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

typeorm ํŠน์ง•๊ณผ ์ด์ 

  • ๋ชจ๋ธ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ” ์ฒด๊ณ„๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑ
  • ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ๊ฐ์ฒด ์‰ฝ๊ฒŒ ์‚ฝ์ž…, ์—…๋ฐ์ดํŠธ ๋ฐ ์‚ญ์ œ๊ฐ€๋Šฅ
  • ํ…Œ์ด๋ธ” ๊ฐ„์˜ ๋งคํ•‘(1:1,1:N,M:N)์„ ๋งŒ๋“ฆ
  • ๊ฐ„๋‹จํ•œ CLI ๋ช…๋ น์„ ์ œ๊ณต
  • typeorm์€ ๊ฐ„๋‹จํ•œ ์ฝ”๋”ฉ์œผ๋กœ ORM ํ”„๋ ˆ์ž„์›Œํฌ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๋‹ค
  • typeorm์€ ๋‹ค๋ฅธ ๋ชจ๋“ˆ๊ณผ ์‰ฝ๊ฒŒ ํ†ตํ•ฉ๋œ๋‹ค.

1. typeorm ์‚ฌ์šฉํ•˜๋Š” ๋ฒ•

1.npm install @nestjs/typeorm

  • nestjs์—์„œ typeorm์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์—ฐ๋™์‹œ์ผœ์ฃผ๋Š” ๋ชจ๋“ˆ

2.npm install --save typeorm pg

  • typeorm ๋ชจ๋“ˆ๊ณผ postgres ๋ชจ๋“ˆ

connection Option์„ ์ž‘์„ฑ

1. ์ฝ”๋“œ์— ์ง์ ‘ ์“ฐ๋Š” ๋ฐฉ์‹

config/typerom.cofig.ts

import { TypeOrmModuleOptions } from '@nestjs/typeorm';
export const typeORMConfig: TypeOrmModuleOptions = {
  type: 'postgres',
  host: 'localhost',
  port: 5432,
  username: 'postgres',
  password: '2qordjr10',
  database: 'board-app',
  entities: [__dirname + '/../**/*.entity.{js,ts}'],
  synchronize: true,
};
  • app.module์— ์—ฐ๊ฒฐ
@Module({
  imports: [
    TypeOrmModule.forRoot(typeORMConfig),
  ],
})

2. ormconfig.jsonํŒŒ์ผ์— ์“ฐ๋Š”๋ฒ•

  • app.module
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { TypeOrmModule } from '@nestjs/typeorm';
import { RestaurantsModule } from './restaurants/restaurants.module';
@Module({
  imports: [
    GraphQLModule.forRoot({
      autoSchemaFile: true,
    }),
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'minjaekim',
      password: '2qordjr10',
      database: 'minber-eats',
      synchronize: true,
      // ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์—์„œ ๋ชจ๋“ˆ์˜ ํ˜„์žฌ์ƒํƒœ๋กœ ๋งˆ์ดํฌ๋ ˆ์ด์…˜
      logging: false,
    }),
    RestaurantsModule,
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}

2. Configuration

  1. npm i --save @nestjs/config
  • dotenv ์ ‘๊ทผ ํ•˜๋Š” ๋ฐฉ๋ฒ•, config ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜๋ฉด dotenv๋ฅผ ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  1. npm i cross-env
  • ๊ฐ€์ƒ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.
  1. "start:dev": "cross-env Env=dev nest start --watch"
  • scripts์— cross-env๋ฅผ ์ ์–ด์ฃผ๊ณ  Env=dev๋ฅผ ์ ์–ด์ค€๋‹ค.
  • app.module
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: process.env.NODE_ENV === 'dev' ? '.env.dev' : '.env.test',
    }),
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'minjaekim',
      password: '2qordjr10',
      database: 'minber-eats',
      synchronize: true,
      logging: false,
    }),
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}
  • isGlobal์€ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์–ด๋””์„œ๋‚˜ config ๋ชจ๋“ˆ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•ด์ฃผ๊ณ 
  • envFilePath์€ ๋ณ€์ˆ˜๋ฅผ ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ์ ‘๊ทผ ํ•˜๋„๋ก npm ํ™˜๊ฒฝ ์„ค์ •์„ ํ•ด ์ค„ ์ˆ˜ ์žˆ๋‹ค.

3. Configuring ConfigService

  • ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ TypeOrmModule.forRoot์— ์ ์€ ๋‚ด์šฉ์„ ์˜ฎ๊ฒจ์ค€๋‹ค.

.env.dev

DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=minjaekim
DB_PASSWORD=2qordjr10
DB_NAME=minber-eats]
  • app.module
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: process.env.NODE_ENV === 'dev' ? '.env.dev' : '.env.test',
      ignoreEnvFile: process.env.NODE_ENV === 'prod',
    }),
    GraphQLModule.forRoot({
      autoSchemaFile: true,
    }),
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: process.env.DB_HOST,
      port: +process.env.DB_PORT,
      username: process.env.DB_USERNAME,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_NAME,
      synchronize: true,
      logging: true,
    }),
    RestaurantsModule,
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}

-ignoreEnvFile์€ ์„œ๋ฒ„์— ๋ฐฐํฌํ•  ๋•Œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ํŒŒ์ผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋„๋ก ํ•˜์—ฌ prod ํ™˜๊ฒฝ์ผ ๋•Œ ConfigModule์€ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ํŒŒ์ผ์„ ๋ฌด์‹œํ•œ๋‹ค.
"start": "cross-env NODE_ENV=prod nest start"

  • scripts์— start๋ถ€๋ถ„ cross-env NODE_ENV=prod ๋ฐฐํฌ ์‹œ์—๋งŒ ๋˜๋„๋ก ์„ค์ •ํ•˜๊ธฐ

4.Joi

  • Joi๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์šฉ์˜ ์Šคํ‚ค๋งˆ ์„ค๋ช… ์–ธ์–ด์ด์ž ๋ฐ์ดํ„ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ์šฉ ํˆด์ด๋‹ค.
  1. npm i joi
  • ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ํ†ตํ•ด์„œ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋“ค์ด ์ค€๋น„๋˜์ง€ ์•Š์œผ๋ฉด ์•ฑ์ด ์‹คํ–‰ ์•ˆ๋˜๋ก ํ•œ๋‹ค.
  1. import * as Joi from 'joi';
  • ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒจํ‚ค์ง€๋Š” ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋กœ ๋งŒ๋“ค์–ด์žˆ์ง€ ์•Š๊ธฐ๋•Œ๋ฌธ์— importํ•˜๋Š” ๋ฐฉ์‹์ด ๋‹ค๋ฆ„
  • importํ•œ Joi objectํ™œ์šฉํ•˜์—ฌ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋งˆ์ € ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  1. Joi๋Š” string์ด ๋˜์–ด์•ผํ•˜๋ฉฐ valid์•ˆ์— ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋“ค์„ ์ ์–ด์ค€๋‹ค.
ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: process.env.NODE_ENV === 'dev' ? '.env.dev' : '.env.test',
      ignoreEnvFile: process.env.NODE_ENV === 'prod',
      validationSchema: Joi.object({
        NODE_ENV: Joi.string().valid('dev', 'prod').required(),
        DB_HOST: Joi.string().required(),
        DB_PORT: Joi.string().required(),
        DB_USERNAME: Joi.string().required(),
        DB_PASSWORD: Joi.string().required(),
        DB_NAME: Joi.string().required(),
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: process.env.DB_HOST,
      // ์ˆซ์ž๊ฐ€ ๋“ค์–ด๊ฐ„ string(EX>"5302")์„ num์œผ๋กœ ๋ฐ”๊พธ๊ธฐ ์œ„ํ•ด์„œ+๋ฅผ ์•ž์— ๋ถ™์—ฌ์ฃผ๋ฉด๋จ
      port: +process.env.DB_PORT,
      username: process.env.DB_USERNAME,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_NAME,
      synchronize: true,
      logging: true,
    }),
 

*๐Ÿ’กconclusion

  • ๐Ÿ”‘TypeORM์„ ์“ฐ๋Š” 2๊ฐ€์ง€ ๋ฐฉ์‹๊ณผ & ๐Ÿ”‘Configuring ์„ค์ •ํ•˜๋Š” ๋ฐฉ์‹์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋‘์ž 

#๐Ÿ“‘Study Source

  • ๋‹ˆ๊ผด๋ผ์Šค ์Œค ์šฐ๋ฒ„์ด์ธ  ๊ฐ•์˜ ์ค‘:-
profile
์ž๊ธฐ ์‹ ๋ขฐ์˜ ํž˜์„ ๋ฏฟ๊ณ  ์‹ค์ฒœํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๊ณ ์žํ•ฉ๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€