✔️ OOP 를 사용해서 데이터베이스 테이블을 클래스로 관리 할 수 있게 해주는 ORM 이다.
✔️ 다양한 데이터베이스를 지원한다. MySQL, PostgreSQL, MariaDB, SQLite, Oracle, Mongodb
✔️ Active Record 와 Data Mapper 패턴을 모두 지원한다.
✔️ 자체적으로 Migration 기능을 지원하며 점진적인 데이터베이스 구조 변경과 버저닝을 모두 지원한다.
✔️ Eager & Lazy 로딩을 모두 지원하기 때문에 어떤 방식으로 데이터를 불러올지 완전한 컨트롤이 가능하다.
📌 사용할 데이터베이스 지정 및 정보 제공 역할
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()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
firstName: string
@Column()
lastName: string
@Column()
isAcitve: boolean }
@Entity Annotation을 사용하면 클래스를 테이블로 관리 할 수 있다.
@Column Annotaion을 사용하면 테이블의 칼럼을 생성 할 수 있다.
@PrimaryGeneratedColumn은 자동 생성 되는 ID 칼럼을 생성 할 수 있다.
📌 Column 옵션은 첫번째 파라미터에 객체로 제공할 수 있다.
@Entity()
export class User{
@Column({
type: "varchar",
length: 150,
unique: true,
})
name: string;
}
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[]
@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씩 증가한다.
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 {}
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를 주입받아, 환경 변수 값을 동적으로 설정