TypeORM

김영훈·2024년 11월 26일

NestJS

목록 보기
3/9
post-thumbnail

TypeORM

TypeORM 특성

✔️ OOP 를 사용해서 데이터베이스 테이블을 클래스로 관리 할 수 있게 해주는 ORM 이다.
✔️ 다양한 데이터베이스를 지원한다. MySQL, PostgreSQL, MariaDB, SQLite, Oracle, Mongodb
✔️ Active RecordData Mapper 패턴을 모두 지원한다.
✔️ 자체적으로 Migration 기능을 지원하며 점진적인 데이터베이스 구조 변경과 버저닝을 모두 지원한다.
✔️ Eager & Lazy 로딩을 모두 지원하기 때문에 어떤 방식으로 데이터를 불러올지 완전한 컨트롤이 가능하다.


DataSource

📌 사용할 데이터베이스 지정 및 정보 제공 역할

const PostgresDataSource = new DataSource({  
    type: "postgres",  
    host: "localhost",  
    port: 5432,  
    username: "test",  
    password: "test",  
    database: "test",  
    entities: [  
        // 여기에 Entity 들 입력  
    ]  
})  

type: 데이터베이스종류
host: 연결 호스트
port: 연결 포트
username: 아이디
password: 비밀번호
database: 연결 데이터베이스
entities: TS 엔티티 객체

Entity

@Entity()  
export class User {  
    @PrimaryGeneratedColumn()  
    id: number   
      
@Column()  
    firstName: string   
      
@Column()  
    lastName: string   
      
@Column()  
    isAcitve: boolean }  

@Entity Annotation을 사용하면 클래스를 테이블로 관리 할 수 있다.
@Column Annotaion을 사용하면 테이블의 칼럼을 생성 할 수 있다.
@PrimaryGeneratedColumn은 자동 생성 되는 ID 칼럼을 생성 할 수 있다.


### Column 옵션

📌 Column 옵션은 첫번째 파라미터에 객체로 제공할 수 있다.

@Entity()  
export class User{  
    @Column({  
        type: "varchar",  
        length: 150,  
        unique: true,  
    })  
    name: string;  
}  

주요 Column 옵션(1)

type:ColumnType : 칼럼 타입, varchar, text, int, bool 등 칼럼 타입
name: string : 데이터베이스에 저장될 칼럼 이름. 기본값은 프로퍼티 이름을 따른다.
nullable: boolean : Null 값이 가능한지 여부. 기본 값은 false 다.
update:boolean : 업데이트 가능 여부. false 일 경우 저장 후 업데이트 불가. 기본값 true
select: boolean : 쿼리 실행시 프로퍼티를 가져올지 결정. false 일 경우 가져오지 않는게 기본.
default: string : 칼럼 기본값
unique: boolean : unique constraint 적용 여부, 기본 false
comment: string : 칼럼 코멘트. 모든 데이터베이스에서 지원되진 않음.
enum:string[] : 칼럼에 입력 가능한 값을 enum 으로 나열
array:boolean : 칼럼 array 타입으로 생성. 예) int[]

특수 Column

@Entity()  
export class User {  
    @CreateDateColumn()  
    createdAt: Date;  
      
    @UpdateDateColumn()  
    updatedAt: Date;  
      
    @DeleteDateColumn()  
    deletedAt: Date;   
      
    @VersionColumn()  
    version: number;  
}  

@CreatedDateColumn 은 자동으로 Row 생성 날짜시간을 저장한다.
@UpdatedDateColumn은 자동으로 Row 최근 업데이트 날짜시간을 저장한다.
@DeletedDateColumn 은 자동으로 Row 의 SoftDelete 시간을 저장한다.
@VersionColumn 은 자동으로 Row 가 업데이트 될때마다 1씩 증가한다.

TypeORM 연동 예시

pnpm i @nestjs/config joi @nestjs/typeorm typeorm pg  
import { Module } from '@nestjs/common';  
import { MovieModule } from './movie/movie.module';  
import {TypeOrmModule} from "@nestjs/typeorm";  
  
@Module({  
  imports: [  
      TypeOrmModule.forRoot({  
          type: "postgres",  
          host: "localhost",  
          port: 5432,  
          username: "myuser",  
          password: "mypassword",  
          database: "mydatabase",  
          entities: [],  
          synchronize: true,  
      })  
      ,MovieModule  
  ],  
})  
export class AppModule {}  
  
# dev = 개발  
# prod = 배포  
ENV=dev  
  
# DB  
DB_TYPE=postgres  
DB_HOST=localhost  
DB_PORT=5432  
DB_USERNAME=myuser  
DB_PASSWORD=mypassword  
DB_DATABASE=mydatabase  
  
import { Module } from '@nestjs/common';  
import { MovieModule } from './movie/movie.module';  
import {TypeOrmModule} from "@nestjs/typeorm";  
import {ConfigModule} from "@nestjs/config";  
  
@Module({  
  imports: [  
      ConfigModule.forRoot(),  
      TypeOrmModule.forRoot({  
          type: process.env.DB_TYPE as "postgres",  
          host: process.env.DB_HOST,  
          port: parseInt(process.env.DB_PORT),  
          username: process.env.DB_USERNAME,  
          password: process.env.DB_PASSWORD,  
          database: process.env.DB_DATABASE,  
          entities: [],  
          synchronize: true,  
      })  
      ,MovieModule  
  ],  
})  
export class AppModule {}  
  

JOI 를 활용한 스키마 validation

import { Module } from '@nestjs/common';  
import { MovieModule } from './movie/movie.module';  
import {TypeOrmModule} from "@nestjs/typeorm";  
import {ConfigModule} from "@nestjs/config";  
import * as Joi from "joi";  
  
@Module({  
  imports: [  
      ConfigModule.forRoot({  
          isGlobal: true, // ConfigModule 에 정의한 환경변수들을 어떤 모듈에서든 사용가능하게 함  
          validationSchema: Joi.object({  
              ENV: Joi.string().required(),  
              DB_TYPE: Joi.string().required(),  
              DB_HOST: Joi.string().required(),  
              DB_PORT: Joi.number().required(),  
              DB_USERNAME: Joi.string().required(),  
              DB_PASSWORD: Joi.string().required(),  
              DB_DATABASE: Joi.string().required(),  
          })  
      }),  
      TypeOrmModule.forRoot({  
          type: process.env.DB_TYPE as "postgres",  
          host: process.env.DB_HOST,  
          port: parseInt(process.env.DB_PORT),  
          username: process.env.DB_USERNAME,  
          password: process.env.DB_PASSWORD,  
          database: process.env.DB_DATABASE,  
          entities: [],  
          synchronize: true,  
      })  
      ,MovieModule  
  ],  
})  
export class AppModule {}  
  
import { Module } from '@nestjs/common';  
import { MovieModule } from './movie/movie.module';  
import {TypeOrmModule} from "@nestjs/typeorm";  
import {ConfigModule} from "@nestjs/config";  
import * as Joi from "joi";  
  
@Module({  
  imports: [  
      ConfigModule.forRoot({  
          isGlobal: true, // ConfigModule 에 정의한 환경변수들을 어떤 모듈에서든 사용가능하게 함  
          validationSchema: Joi.object({  
              ENV: Joi.string().required(),  
              DB_TYPE: Joi.string().valid('postgres').required(),  
              DB_HOST: Joi.string().required(),  
              DB_PORT: Joi.number().required(),  
              DB_USERNAME: Joi.string().required(),  
              DB_PASSWORD: Joi.string().required(),  
              DB_DATABASE: Joi.string().required(),  
          }),  
      }),  
      TypeOrmModule.forRoot({  
          type: process.env.DB_TYPE as "postgres",  
          host: process.env.DB_HOST,  
          port: parseInt(process.env.DB_PORT),  
          username: process.env.DB_USERNAME,  
          password: process.env.DB_PASSWORD,  
          database: process.env.DB_DATABASE,  
          entities: [],  
          synchronize: true,  
      })  
      ,MovieModule  
  ],  
})  
export class AppModule {}  
  
import { Module } from '@nestjs/common';  
import { MovieModule } from './movie/movie.module';  
import {TypeOrmModule} from "@nestjs/typeorm";  
import {ConfigModule, ConfigService} from "@nestjs/config";  
import * as Joi from "joi";  
  
@Module({  
  imports: [  
      ConfigModule.forRoot({  
          isGlobal: true, // ConfigModule 에 정의한 환경변수들을 어떤 모듈에서든 사용가능하게 함  
          validationSchema: Joi.object({  
              ENV: Joi.string().valid('dev', 'prod').required(),  
              DB_TYPE: Joi.string().valid('postgres').required(),  
              DB_HOST: Joi.string().required(),  
              DB_PORT: Joi.number().required(),  
              DB_USERNAME: Joi.string().required(),  
              DB_PASSWORD: Joi.string().required(),  
              DB_DATABASE: Joi.string().required(),  
          }),  
      }),  
      /*TypeOrmModule.forRoot({  
          type: process.env.DB_TYPE as "postgres",  
          host: process.env.DB_HOST,  
          port: parseInt(process.env.DB_PORT),  
          username: process.env.DB_USERNAME,  
          password: process.env.DB_PASSWORD,  
          database: process.env.DB_DATABASE,  
          entities: [],  
          synchronize: true,  
      })*/  
      TypeOrmModule.forRootAsync({  
          useFactory: (configService: ConfigService) => ({  
              type: configService.get<string>("DB_TYPE") as "postgres",  
              host: configService.get<string>("DB_HOST"),  
              port: configService.get<number>("DB_PORT"),  
              username: configService.get<string>("DB_USERNAME"),  
              password: configService.get<string>("DB_PASSWORD"),  
              database: configService.get<string>("DB_DATABASE"),  
              entities: [],  
              synchronize: true,  
          }),  
          inject: [ConfigService]  // ConfigService를 주입
      }),  
      MovieModule  
  ],  
})  
export class AppModule {}  
  

ConfigModule : Global 설정을 통해 별다른 설정없이 다른 모듈에서 ConfigService를 주입받아 사용 가능
TypeOrmModule.forRootAsync : 비동기적으로 데이터베이스 설정을 초기화 할 수 있는 기능 제공.
ConfigService : ConfigModule 에서 등록한 환경변수를 읽을 수 있는 서비스.
useFactory 함수에서 ConfigService를 주입받아, 환경 변수 값을 동적으로 설정

0개의 댓글