[TypeORM] Start with Nest

[์›๋ณธ ๋งํฌ]

TypeOrm์€ ๋Œ€ํ‘œ์ ์ธ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ๊ธฐ๋ฐ˜์˜ ORM ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‹ค.
Sequelize๋Š” ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ์ง€์›์ด ๋ถ€์‹คํ•˜๊ณ , Prisma ๊ฐ™์€ ํ›„๋ฐœ์ฃผ์ž๋“ค์€ ์ข€ ๋ถˆ์•ˆ์ •ํ•˜๊ธฐ ๋•Œ๋ฌธ์—,
ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ™˜๊ฒฝ์—์„œ ORM์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด 1์ˆœ์œ„๋กœ ์„ ํƒ๋˜๋Š” ์นœ๊ตฌ๋‹ค.

์•„๋ฌด๋ฐ๋‚˜ ๋ถ™์—ฌ๋„ ๋˜์ง€๋งŒ, ์—ฌ๊ธฐ์„œ๋Š” Nest์— ๋ถ™์—ฌ๋ณด๋ฉด์„œ ํ…Œ์ŠคํŠธ๋ฅผ ๊ฐ„๋žตํ•˜๊ฒŒ ํ•ด๋ณด๊ฒ ๋‹ค.




์„ค์น˜

์„ค์น˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•  ์ˆ˜ ์žˆ๋‹ค.
typeorm ๋ชจ๋“ˆ๊ณผ ์‚ฌ์šฉํ•  DB ๋ชจ๋“ˆ์„ ์„ค์น˜ํ•œ๋‹ค.

๋‚˜๋Š” postgres๋ฅผ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— pg๋ฅผ ์„ค์น˜ํ–ˆ๋Š”๋ฐ, mysql์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด mysql์„ ๊น”๋ฉด ๋œ๋‹ค.
์•„๋ž˜๋Š” DB์— ๋”ฐ๋ฅธ ์ถ”๊ฐ€ ์„ค์น˜ ๋ชจ๋“ˆ์ด๋‹ค.

์•Œ๋‹ค์‹œํ”ผ Nest์˜ ๊ฐ•๋ ฅํ•œ ๊ฐ•์  ์ค‘ ํ•˜๋‚˜๊ฐ€ ์˜์กด์„ฑ ์ฃผ์ž…์„ ํ†ตํ•œ ๊ฐ์ฒด์˜ ๊ณต์œ ์™€ ์‚ฌ์šฉ์ด๋‹ค.
๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๋˜, ์˜์กด์„ฑ ์ฃผ์ž…์œผ๋กœ ํ•ด๋‹น ์ปค๋„ฅ์…˜์„ ๊ฐ–๋‹ค์“ธ ์ˆ˜ ์žˆ๋„๋ก ํ•  ๊ฒƒ์ด๋‹ค.




์ปค๋„ฅ์…˜ ์„ค์ •ํ•˜๊ธฐ

์ด๋ฅผ ์œ„ํ•œ ํ”„๋กœ๋ฐ”์ด๋” ์†Œ์Šค database.ts๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ‘์† ์ •๋ณด๋“ค์„ ์ž˜ ์จ์ฃผ๋ฉด ๋œ๋‹ค.

import { Connection, createConnection } from 'typeorm';

export const databaseProvider = {
  provide: Connection,
  useFactory: async () =>
    await createConnection({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'nest_user',
      password: 'asdf123',
      database: 'nest_test',
      entities: [__dirname + '/../**/*.entity{.ts,.js}'],
      synchronize: true,
      logging: 'all',
    }),
};

์—ฌ๊ธฐ์„  ์ดˆ๊ธฐ ์ƒ์„ฑ๋‹จ๊ณ„๋ผ synchronize: true, ์˜ต์…˜์„ ์คฌ๋Š”๋ฐ, ๊ณ„์† ์ด๋Ÿฌ๋ฉด ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜ ๋ฐ”๋€”๋•Œ๋งˆ๋‹ค ๊ฐ•์ œ๋กœ ํ…Œ์ด๋ธ”๋ฅผ ๋ฆฌ์…‹ํ•  ์ˆ˜๊ฐ€ ์žˆ๋‹ค.
๊ทธ๋ž˜์„œ ์ œ๋Œ€๋กœ ๋ฐฐํฌ๋ฅผ ํ–ˆ์„ ๋•Œ๋Š” false๋กœ ์ฃผ๊ณ  ์•ˆ์ „ํ•˜๊ฒŒ ์ž˜ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜์„ ์ฃผ์ž…ํ•˜๊ธฐ ์œ„ํ•ด์„œ, ์ด๊ฑธ ๋ชจ๋“ˆ์— ๋„ฃ์–ด์ค€๋‹ค.
๋‚˜๋Š” database.module์ด๋ผ๋Š” ๋ณ„๋„์˜ ๋ชจ๋“ˆ์„ ์ •์˜ํ•ด์„œ

import { Module } from '@nestjs/common';
import { databaseProvider } from './../provider/database';

@Module({ providers: [databaseProvider], exports: [databaseProvider] })
export class DatabaseModule {}

๋ฃจํŠธ๋ชจ๋“ˆ์— ๋„ฃ์–ด์ฃผ๋„๋ก ํ–ˆ๋‹ค.

import { Module } from '@nestjs/common';
import { AppController } from './../controller/app.controller';
import { AppService } from './../app.service';
import { DatabaseModule } from './database.module';

@Module({
  imports: [DatabaseModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

ํ”„๋กœ๋ฐ”์ด๋”๋ฅผ ๊ทธ๋ƒฅ ๋ฃจํŠธ์— ๋•Œ๋ ค๋ฐ•์•„๋„ ๋˜๊ธด ํ•˜๋Š”๋ฐ ๊ณต์‹๋ฌธ์„œ์—์„œ ๊ทธ๋Ÿฌ๊ธธ๋ž˜ ๋˜‘๊ฐ™์ด ํ–ˆ๋‹ค.




์—”ํ‹ฐํ‹ฐ ์ •์˜ํ•˜๊ธฐ

๊ทธ๋Ÿผ ์ด์ œ ๋งคํ•‘์‹œํ‚ฌ ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•œ๋‹ค.
์‹ค์ œ ํ…Œ์ด๋ธ”๊ณผ 1:1๋กœ ๋งค์นญ๋  ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋‹ค.
๋‚˜๋Š” User ํ…Œ์ด๋ธ”๊ณผ ๊ทธ ์‚ฌ์šฉ์ž๋“ค์ด ์ž‘์„ฑํ•˜๋Š” Post์— ๋Œ€ํ•œ ํ…Œ์ด๋ธ” 2๊ฐœ๋ฅผ ์ž‘์„ฑํ•˜๊ฒ ๋‹ค.

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

@Entity()
export class User {
  @PrimaryGeneratedColumn() // ๊ธฐ๋ณธํ‚ค
  id: number;

  @Column()
  email: string;

  @Column()
  password: string;

  @Column()
  name: string;
}
// post.entity.ts
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Post {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  user_id: string;

  @Column()
  content: string;
}

ํŠน๋ณ„ํ•  ๊ฒƒ์€ ์—†๋‹ค.
@Entity ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ ํ•ด๋‹น ํƒ€์ž…์ด ํ…Œ์ด๋ธ”์— ๋งค์นญ๋  ๊ตฌ์กฐ์ž„์„ ๋ช…์‹œํ•˜๊ณ , ํ•„๋“œ๋งˆ๋‹ค Column ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ๋‹ฌ์•„์„œ ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ์ž„์„ ๋ช…์‹œํ•˜๋ฉด ๋œ๋‹ค.
PrimaryGeneratedColumn๋Š” ๊ธฐ๋ณธํ‚ค ์ปฌ๋Ÿผ์šฉ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋‹ค.

ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ฉด typeorm์ด ํ•„๋“œ ํƒ€์ž…์„ ์ฝ์–ด์„œ ์ปฌ๋Ÿผํƒ€์ž…๋„ ์•Œ์•„์„œ ์ž˜ ๋งž์ถฐ์ฃผ๋Š”๋ฐ, ์ปฌ๋Ÿผํƒ€์ž…์„ ์ง์ ‘ ์ง€์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด

@Column('TEXT')
user_id: string;

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์— ๋ฌธ์ž์—ด ์ธ์ž๋กœ ์จ์ฃผ๋ฉด ๋œ๋‹ค.




์ปค๋„ฅ์…˜ ์ฃผ์ž…ํ•˜๊ธฐ

์œ„์—์„œ ๋งŒ๋“  ์ปค๋„ฅ์…˜์„ ์ด์ œ ๊ฐ–๋‹ค์จ๋ณด์ž.
๋ฐฉ๋ฒ•์€ ์‰ฝ๋‹ค. ์ปจํŠธ๋กค๋Ÿฌ ํ•„๋“œ ์•„๋ฌด๋ฐ๋‚˜

์ด๋Ÿฐ์‹์œผ๋กœ ๋ฐ•์•„๋‘๋ฉด ๋œ๋‹ค.
nest๊ฐ€ ์œ„์—์„œ ์ •์˜ํ•œ ์ปค๋„ฅ์…˜์„ ์ฝ์–ด์„œ ์ž˜ ๋„ฃ์–ด์ค€๋‹ค.




์ฟผ๋ฆฌ ๋นŒ๋”

๊ทธ๋Ÿฌ๋ฉด ์ด์ œ ์ปค๋„ฅ์…˜์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด์„œ, ์ฟผ๋ฆฌ๋นŒ๋” ๋“ฑ์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.
๋‹ค์Œ์€ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜ ์‚ฝ์ž…ํ•˜๋Š” ์ฟผ๋ฆฌ๋‹ค.
into์— ์‚ฝ์ž…ํ•  ํ…Œ์ด๋ธ” ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ „๋‹ฌ, values์— ์‚ฝ์ž…ํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ๊ณ ,
execute๋กœ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ์‚ฝ์ž…๋  ๊ฒƒ์ด๋‹ค.

์œ„์˜ api๋ฅผ ์‹คํ–‰ํ•œ๋‹ค๋ฉด

๋™๊ธฐํ™” ์˜ต์…˜์„ ์คฌ์œผ๋‹ˆ ์—†๋Š” ํ…Œ์ด๋ธ”์€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜์—ˆ์„ ๊ฒƒ์ด๊ณ 

๋ฐ์ดํ„ฐ๋„ ์‚ฝ์ž…๋˜์—ˆ์„ ๊ฒƒ์ด๋‹ค.

select๋ฅผ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ์‹์œผ๋กœ ํ•  ์ˆ˜ ์žˆ๋‹ค.

select๋Š” select ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ๊ฒ ๋‹ค๋Š” ๊ฒƒ์ด๊ณ , from์€ ์ฝ์–ด์˜ฌ ํ…Œ์ด๋ธ”์ด๋‹ค.
์ฟผ๋ฆฌ๋นŒ๋”๋Š” ๋นŒ๋” ํŒจํ„ด์œผ๋กœ ๊ตฌ์ถ•๋œ ๊ตฌ์กฐ๋ผ, ์ „๋ถ€ ์œ„์ฒ˜๋Ÿผ ๋ฉ”์„œ๋“œ ์ฒด์ด๋‹์œผ๋กœ ์ฟผ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

์ด์™ธ์—๋„ ์ฟผ๋ฆฌ๋นŒ๋”์—๋Š” ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ๋“ค์ด ์žˆ๊ณ , ์™ธ์—๋„ repository ํŒจํ„ด ๋“ฑ์˜ ํ™”๋ คํ•œ ๊ธฐ๋Šฅ๋“ค์ด ์กด์žฌํ•˜๋‚˜.
์ž์„ธํ•œ ๊ฒƒ๋“ค์€ ๋‹ค์Œ ํฌ์ŠคํŠธ์—์„œ ์ฒœ์ฒœํžˆ ๋‹ค๋ฃจ๋„๋ก ํ•˜๊ฒ ๋‹ค.



์ฐธ์กฐ
https://docs.nestjs.com/recipes/sql-typeorm
https://orkhan.gitbook.io/typeorm/docs/logging