01. type orm
nest에서 가장 많이 사용하는 orm이라고 한다.
아무레도 nest와 typeorm둘다 데코레이터 패턴을 사용하기도 하고 ts기반이라서 타입안정성을 제공 해서? 는 헛소리고 nest에서 밀어주는 듯한 기분이 드는 orm이라고 생각한다.
장점으로는
- nestjs에서 공식적으로 지원하는 ORM
- nestjs로 구성한 서버와 RDB 서버간 패러다임의 불일치를 줄이기 위해 사용
- 타입스크립트와 자바스크립트(ES5, ES6, ES7, ES8)와 함께 사용할 수 있다
- 경험해보진 않았지만 시퀄라이즈ORM보다 typescript과의 융합이 잘 된다고 한다.
- typescript를 다른 ORM보다 강력하게 지원한다는 점
이라고는 하는데 아직은 모르겠다 솔직히...
02. TypeORM Model Generato
db에서 엔티티들 다 만들었는데 이거를 직접 작성을 안하고 이거를 이용하면 알아서 작성이 된다고 한다.
npm i typerom-model-generator -D
순서는 주소명 디비명 사용자명 비밀번호 db종류(mysql 마리아디비 등등)
npx typeorm-model-generator -h localhost -d konnect -u root -x 702255 -e mysql
03. db설정
db는 간단하게 mysql을 사용할껀데 아래처럼 써보자.
// app.module.ts
imports: [
// dotenv 전역사용
ConfigModule.forRoot({
isGlobal: true,
}),
UsersModule,
MentoModule,
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3030,
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
// 직접 만들고 db에 만들때
synchronize: true,
logging: true,
// 핫리로드 시 db끊기는거 막기
keepConnectionAlive: true,
// 이모티콘을 사용하기 위해 쓰는거
charset: 'utf8mb4',
// autoLoadEntities 이거는 추후에 만들꺼에서 엔티티를 자동으로 넣어주는거
// 버그가 있을수 잇어 나는 별루...
entities: [
Comments,
Likes,
MentoringPrograms,
Mentos,
Payments,
Posts,
Users,
],
}),
],
하지만 위처럼만 하면 당연히 안된다 왜냐? db를 안만들엇거든.... 그레서 db한번 만들어 보장
그리고 초기 데이터를 넣는 작업을 해보자.
초기 데이터를 넣기 위해서는 일단 하나를 설치후 추가 해야된다.
설치및 추가 하고 db를 생성한다.
하지만 처음부터 되진 않더라....
npm i typeorm-extension
// package.json
// 아래 추가
"typeorm": "ts-node --require tsconfig-paths/register ./node_modules/typeorm/cli.js",
// 데이터베이스 생성
"db:create": "ts-node ./node_modules/typeorm-extension/bin/cli.cjs db:create -d ./dataSource.ts",
// 데이터베이스 삭제
"db:drop": "ts-node ./node_modules/typeorm-extension/bin/cli.cjs db:drop -d ./dataSource.ts",
// 초창기 데이터 넣기
"seed": "ts-node ./node_modules/typeorm-extension/bin/cli.cjs seed -d ./dataSource.ts",
"schema:drop": "ts-node ./node_modules/typeorm/cli.js schema:drop",
"schema:sync": "ts-node ./node_modules/typeorm/cli.js schema:sync",
"db:migrate": "npm run typeorm migration:run -- -d ./dataSource.ts",
"db:migrate:revert": "npm run typeorm migration:revert -- -d ./dataSource.ts",
"db:create-migration": "npm run typeorm migration:create -- ./src/migrations/",
"db:generate-migration": "npm run typeorm migration:generate -- ./src/migrations -d ./dataSource.ts"
npm run db:create
추가 되지 않으면 어떻게 해야되냐 방법은 찾아야지...그레서 하나의 파일을 루트에 만든다.
// 루트에 dataSource.ts 생성
import { DataSource } from 'typeorm';
import dotenv from 'dotenv';
import { Comments } from 'src/entities/Comments';
import { Likes } from 'src/entities/Likes';
import { MentoringPrograms } from 'src/entities/MentoringPrograms';
import { Mentos } from 'src/entities/Mentos';
import { Payments } from 'src/entities/Payments';
import { Posts } from 'src/entities/Posts';
import { Users } from 'src/entities/Users';
dotenv.config();
const dataSource = new DataSource({
type: 'mysql',
host: 'localhost',
port: 3306,
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
entities: [
Comments,
Likes,
MentoringPrograms,
Mentos,
Payments,
Posts,
Users,
],
migrations: [__dirname + '/src/migrations/*.ts'],
charset: 'utf8mb4_general_ci',
synchronize: false,
logging: true,
});
export default dataSource;
여기서 좀 충격적일수도 잇는게 디비에서 포트랑 호스트 잘봐라... 이상한거 쓰면 연결안된다 ㅠㅠ
쨋든 이거 하고 npm run start:dev를 하면 만들어둔 테이블이 전부 만들어진다.
그리고 디비 포트와 서버포트는 다르니 확인 ㄱㄱ
04. 시드
나는 일단 필요가 없을꺼 같아서 생성은 안햇는데 초기 데이터값을 만들어 주는 창치 라고 한다.
예제는 아래처럼.
이거는 워크스페이스를 하나 만들고 일반이라는 채널을 만드는 거 같다... 근데 나는 딱히...
이거 쓰고 싶으면 아래꺼 쓰고 npm run seed
// database/seeds/create-initial-data.ts
import { Connection } from 'typeorm';
import { Factory, Seeder } from 'typeorm-seeding';
import { Channels } from '../../entities/Channels';
import { Workspaces } from '../../entities/Workspaces';
export class CreateInitialData implements Seeder {
public async run(factory: Factory, connection: Connection): Promise<any> {
await connection
.createQueryBuilder()
.insert()
.into(Workspaces)
.values([{ id: 1, name: 'Sleact', url: 'sleact' }])
.execute();
await connection
.createQueryBuilder()
.insert()
.into(Channels)
.values([{ id: 1, name: '일반', WorkspaceId: 1, private: false }])
.execute();
}
05. 마이그레이션
기존의 테이블을 바꾸기 위한 방법중 하나를 소개 해보겠다.
npm run db:create-migration 을 치면 src파일에 생성이 되는데 이걸 변경을 하는데
// migrations/1724255403541-categoryToType.ts
import { MigrationInterface, QueryRunner } from 'typeorm';
export class Migrations1724255403541 implements MigrationInterface {
// 실제 수행할 카테고리
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'ALTER TABLE `mentions` RENAME COLUMN `category` TO `type`',
);
}
// 롤백할꺼
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'ALTER TABLE `mentions` RENAME COLUMN `type` TO `category`',
);
}
}
// 엔티티가 수정될때
npm run db:generate-migration 이거 쓰면 되는데 드롭되는경우가 잇어서 백퍼 믿지는 말자.
06. 중복되는 dto처리
// 변경전
import { ApiProperty } from '@nestjs/swagger';
export class JoinRequestDto {
@ApiProperty({
example: 'example@gmail.com',
description: '이메일',
required: true,
})
public email: string;
@ApiProperty({
example: '123456Q!',
description: '비밀번호',
required: true,
})
public password: string;
@ApiProperty({
example: '지젤',
description: '이름',
required: true,
})
public name: string;
@ApiProperty({
example: '지젤',
description: '닉네임',
required: true,
})
public nickname: string;
@ApiProperty({
example: '01012345678',
description: '휴대폰번호',
required: true,
})
public phone: number;
}
// 변경후
import { PickType } from '@nestjs/swagger';
import { Users } from 'src/entities/Users';
export class JoinRequestDto extends PickType(Users, [
'email',
'password',
'name',
'nickname',
'phone',
] as const) {
}
아래처럼 어차피 엔티티에서 사용을 한다 라고 하면 더 짧게 쓸수 잇다.
왜냐 Users 엔티티에서 내가 픽한 그니까 특정 속성만 가져다 쓰기 때문에 이게 더 깔끔하고 용량면에서도 좋다.
07. 드디어 서비스