SQL (TypeORM)

SQL (TypeORM)

This chapter applies only to TypeScript

κ²½κ³  이 κΈ°μ‚¬μ—μ„œλŠ” μ»€μŠ€ν…€ ν”„λ‘œ 바이더 λ©”μ»€λ‹ˆμ¦˜μ„ μ‚¬μš©ν•˜μ—¬ TypeORM νŒ¨ν‚€μ§€λ₯Ό 기반으둜 DatabaseModule을 μž‘μ„±ν•˜λŠ” 방법에 λŒ€ν•΄ μ„€λͺ…ν•©λ‹ˆλ‹€. 결과적으둜 이 μ†”λ£¨μ…˜μ—λŠ” μ¦‰μ‹œ μ‚¬μš© κ°€λŠ₯ν•œ μ „μš© @nestjs/typeormνŒ¨ν‚€μ§€λ₯Ό μ‚¬μš©ν•˜μ—¬ μƒλž΅ν•  수 μžˆλŠ” λ§Žμ€ μ˜€λ²„ ν—€λ“œκ°€ ν¬ν•¨λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. μžμ„Έν•œ λ‚΄μš©μ€ [μ—¬κΈ°] (/techniques/sql)λ₯Ό μ°Έμ‘°ν•˜μ‹­μ‹œμ˜€.

TypeORM은 node.js μ„Έκ³„μ—μ„œ κ°€μž₯ μ„±μˆ™ν•œ ORM (Object Relational Mapper)μž…λ‹ˆλ‹€. TypeScript둜 μž‘μ„±λ˜μ—ˆμœΌλ―€λ‘œ Nest ν”„λ ˆμž„ μ›Œν¬μ—μ„œ 잘 μž‘λ™ν•©λ‹ˆλ‹€.

Getting started

이 라이브러리둜 λͺ¨ν—˜μ„ μ‹œμž‘ν•˜λ €λ©΄ ν•„μš”ν•œ λͺ¨λ“  쒅속성을 μ„€μΉ˜ν•΄μ•Όν•©λ‹ˆλ‹€.

$ npm install --save typeorm mysql

μš°λ¦¬κ°€ ν•΄μ•Όν•  첫번째 λ‹¨κ³„λŠ”typeorm νŒ¨ν‚€μ§€μ—μ„œ κ°€μ Έμ˜¨ createConnection()ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ λ°μ΄ν„°λ² μ΄μŠ€μ™€ μ—°κ²°ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. createConnection()ν•¨μˆ˜λŠ” Promiseλ₯Ό λ°˜ν™˜ν•˜λ―€λ‘œ async providerλ₯Ό λ§Œλ“€μ–΄μ•Όν•©λ‹ˆλ‹€.

@@filename(database.providers)
import { createConnection } from 'typeorm';

export const databaseProviders = [
  {
    provide: 'DATABASE_CONNECTION',
    useFactory: async () => await createConnection({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'root',
      database: 'test',
      entities: [
          __dirname + '/../**/*.entity{.ts,.js}',
      ],
      synchronize: true,
    }),
  },
];

warning 힌트 λͺ¨λ²” 사둀에 따라 * .providers.ts 접미사가 μžˆλŠ” λ³„λ„μ˜ 파일둜 μ‚¬μš©μž μ§€μ • κ³΅κΈ‰μžλ₯Ό μ„ μ–Έν–ˆμŠ΅λ‹ˆλ‹€.

그런 λ‹€μŒ λ‚˜λ¨Έμ§€ μ‘μš© ν”„λ‘œκ·Έλž¨μ— λŒ€ν•΄ μ•‘μ„ΈμŠ€ κ°€λŠ₯ν•˜λ„λ‘ 이듀 κ³΅κΈ‰μžλ₯Ό λ‚΄ λ³΄λ‚΄μ•Όν•©λ‹ˆλ‹€.

@@filename(database.module)
import { Module } from '@nestjs/common';
import { databaseProviders } from './database.providers';

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

이제 @Inject() λ°μ½”λ ˆμ΄ν„°λ₯Ό μ‚¬μš©ν•˜μ—¬ Connection 객체λ₯Ό μ£Όμž…ν•  수 μžˆμŠ΅λ‹ˆλ‹€. Connection 비동기 μ œκ³΅μžμ— μ˜μ‘΄ν•˜λŠ” 각 ν΄λž˜μŠ€λŠ” Promiseκ°€ 해결될 λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦½λ‹ˆλ‹€.

Repository pattern

TypeORM은 리포지토리 λ””μžμΈ νŒ¨ν„΄μ„ μ§€μ›ν•˜λ―€λ‘œ 각 μ—”ν„°ν‹°μ—λŠ” 자체 리포지토리가 μžˆμŠ΅λ‹ˆλ‹€. 이 λ¦¬ν¬μ§€ν† λ¦¬λŠ” λ°μ΄ν„°λ² μ΄μŠ€ μ—°κ²°μ—μ„œ 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ 첫째, μš°λ¦¬λŠ” μ΅œμ†Œν•œ ν•˜λ‚˜μ˜ 싀체가 ν•„μš”ν•©λ‹ˆλ‹€. 곡식 λ¬Έμ„œμ—μ„œ Photo μ—”ν‹°ν‹°λ₯Ό μž¬μ‚¬μš© ν•  κ²ƒμž…λ‹ˆλ‹€.

@@filename(photo.entity)
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

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

  @Column({ length: 500 })
  name: string;

  @Column('text')
  description: string;

  @Column()
  filename: string;

  @Column('int')
  views: number;

  @Column()
  isPublished: boolean;
}

Photo μ—”ν‹°ν‹°λŠ” photo 디렉토리에 μ†ν•©λ‹ˆλ‹€. 이 λ””λ ‰ν† λ¦¬λŠ” PhotoModule을 λ‚˜νƒ€λƒ…λ‹ˆλ‹€. 이제 리포지토리 κ³΅κΈ‰μžλ₯Ό λ§Œλ“€μ–΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

@@filename(photo.providers)
import { Connection, Repository } from 'typeorm';
import { Photo } from './photo.entity';

export const photoProviders = [
  {
    provide: 'PHOTO_REPOSITORY',
    useFactory: (connection: Connection) => connection.getRepository(Photo),
    inject: ['DATABASE_CONNECTION'],
  },
];

warning μ•Œλ¦Ό μ‹€μ œ μ‘μš© ν”„λ‘œκ·Έλž¨μ—μ„œλŠ” 맀직 λ¬Έμžμ—΄μ„ ν”Όν•΄μ•Όν•©λ‹ˆλ‹€. PHOTO_REPOSITORY와 DATABASE_CONNECTION은 뢄리 된 constants.ts νŒŒμΌμ— λ³΄κ΄€ν•΄μ•Όν•©λ‹ˆλ‹€.

이제 @Inject() λ°μ½”λ ˆμ΄ν„°λ₯Ό μ‚¬μš©ν•˜μ—¬ Repository<Photo>λ₯Ό PhotoService에 μ£Όμž…ν•  수 μžˆμŠ΅λ‹ˆλ‹€ :

@@filename(photo.service)
import { Injectable, Inject } from '@nestjs/common';
import { Repository } from 'typeorm';
import { Photo } from './photo.entity';

@Injectable()
export class PhotoService {
  constructor(
    @Inject('PHOTO_REPOSITORY')
    private readonly photoRepository: Repository<Photo>,
  ) {}

  async findAll(): Promise<Photo[]> {
    return await this.photoRepository.find();
  }
}

λ°μ΄ν„°λ² μ΄μŠ€ 연결은 λΉ„λ™κΈ°μ΄μ§€λ§Œ NestλŠ” μ΅œμ’… μ‚¬μš©μžκ°€ 이 ν”„λ‘œμ„ΈμŠ€λ₯Ό μ™„μ „νžˆ λ³Ό 수 없도둝 ν•©λ‹ˆλ‹€. PhotoRepositoryλŠ” db 연결을 기닀리고 있으며, PhotoServiceλŠ” μ €μž₯μ†Œλ₯Ό μ‚¬μš©ν•  μ€€λΉ„κ°€ 될 λ•ŒκΉŒμ§€ μ§€μ—°λ©λ‹ˆλ‹€. 각 ν΄λž˜μŠ€κ°€ μΈμŠ€ν„΄μŠ€ν™”λ˜λ©΄ 전체 μ‘μš© ν”„λ‘œκ·Έλž¨μ„ μ‹œμž‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ§ˆμ§€λ§‰ PhotoModule은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

@@filename(photo.module)
import { Module } from '@nestjs/common';
import { DatabaseModule } from '../database/database.module';
import { photoProviders } from './photo.providers';
import { PhotoService } from './photo.service';

@Module({
  imports: [DatabaseModule],
  providers: [
    ...photoProviders,
    PhotoService,
  ],
})
export class PhotoModule {}

warning 힌트 PhotoModule을 루트 ApplicationModule둜 κ°€μ Έ μ˜€λŠ” 것을 μžŠμ§€ λ§ˆμ‹­μ‹œμ˜€.

Last updated

Was this helpful?