Skip to content

4. Database


1. 데이터베이스 생성하기

Postgres를 설치한 후 board-app이라는 데이터베이스를 생성한다.


2. TypeORM 관련 모듈 설치하기

TypeORM은 NodeJS에서 실행되고 TypeScript로 작성된 객체 관계형 매퍼 라이브러리이며, 다양한 데이터베이스 관리 시스템을 지원한다.


다음과 같이 관련 모듈을 설치한다.


npm install --save @nestjs/typeorm typeorm pg


3. TypeORM 애플리케이션에 연결하기

먼저 TypeORM을 애플리케이션에 연결하기 위한 설정 파일을 생성하기 위해 src 디렉터리에 configs 디렉터리를 생성한다.


mkdir src/configs


다음과 같이 설정 파일을 작성하면 되는데, entities 프로퍼티의 경우 엔터티를 직접 입력해도 되지만, autoLoadEntities: true로 지정한 경우 생략할 수 있다.


src/configs/typeorm.config.ts
import { TypeOrmModuleOptions } from "@nestjs/typeorm";

export const typeOrmConfig: TypeOrmModuleOptions = {
  type: "postgres",
  host: "localhost",
  port: 5432,
  username: "postgres",
  password: "postgres",
  database: "board-app",
  autoLoadEntities: true,
  // entities: [Entity1, Entity2, ...],
  synchronize: true,
};


이렇게 구성한 설정 파일을 모든 모듈에서 사용할 수 있도록 루트 모듈의 imports 배열에 넣어준다.


src/app.module.ts
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { BoardsModule } from "./boards/boards.module";
import { typeOrmConfig } from "./configs/typeorm.config";

@Module({
  imports: [TypeOrmModule.forRoot(typeOrmConfig), BoardsModule],
})
export class AppModule {}


4. 게시물을 위한 엔터티 생성하기

엔터티를 생성해서 사용하면 데이터베이스 관련 작업을 편리하게 할 수 있다.


다음과 같이 게시물을 위한 Board 엔터티를 생성해 보자.


src/boards/board.entity.ts
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
import { BoardStatus } from "./board.model";

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

  @Column()
  title: string;

  @Column()
  description: string;

  @Column()
  status: BoardStatus;
}


5. 모듈에 엔터티 등록하기

데이터베이스 관련 작업은 리포지터로 처리하는데, 엔터티를 관리하는 것이라고 생각하면 된다.


먼저 엔터티를 사용하기 위해 Boards 모듈의 imports 배열에 Board 엔터티를 넣어준다.


src/boards/boards.module.ts
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { Board } from "./board.entity";
import { BoardsController } from "./boards.controller";
import { BoardsService } from "./boards.service";

@Module({
  imports: [TypeOrmModule.forFeature([Board])],
  controllers: [BoardsController],
  providers: [BoardsService],
})
export class BoardsModule {}


이제 BoardsServiceconstructor에 리포지터리 boardRepository를 주입하여 생성할 것이다. 먼저 불필요한 코드 및 파일은 정리하기 위해 board.model.tsBoard 인터페이스를 지우고 board-status.enum.ts 파일명으로 변경한 후 종속되는 경로 및 코드를 모두 수정해 준다.


src/boards/board.model.ts
export enum BoardStatus {
  PUBLIC = "PUBLIC",
  PRIVATE = "PRIVATE",
}
mv boards/board.model.ts boards/board-status.enum.ts
import { BadRequestException, PipeTransform } from "@nestjs/common";
import { BoardStatus } from "../board-status.enum";

export class BoardStatusValidationPipe implements PipeTransform {
  readonly StatusOptions = [BoardStatus.PUBLIC, BoardStatus.PRIVATE];

  private isStatusValid(status: any): boolean {
    return this.StatusOptions.includes(status);
  }

  transform(value: any) {
    value = value.toUpperCase();

    if (!this.isStatusValid(value)) {
      throw new BadRequestException(`${value} isn't in the status`);
    }

    return value;
  }
}
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
import { BoardStatus } from "./board-status.enum";

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

  @Column()
  title: string;

  @Column()
  description: string;

  @Column()
  status: BoardStatus;
}
import { Injectable, NotFoundException } from "@nestjs/common";
import { BoardStatus } from "./board-status.enum";
import { CreateBoardDto } from "./dto/create-board.dto";

@Injectable()
export class BoardsService {}
import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  UsePipes,
  ValidationPipe,
} from "@nestjs/common";
import { BoardStatus } from "./board-status.enum";
import { BoardsService } from "./boards.service";
import { CreateBoardDto } from "./dto/create-board.dto";
import { BoardStatusValidationPipe } from "./pipes/board-status-validation.pipe";

@Controller("boards")
export class BoardsController {
  constructor(private boardsService: BoardsService) {}
}


6. 리포지터리 주입하기

Board 엔터티를 관리하는 리포지터리를 사용하려면 다음과 같이 BoardsServiceconstructor 안에 @InjectRepository 데코레이터를 달아준 후 선언하면 된다.


src/boards/boards.service.ts
import { Injectable, NotFoundException } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { BoardStatus } from "./board-status.enum";
import { Board } from "./board.entity";
import { CreateBoardDto } from "./dto/create-board.dto";

@Injectable()
export class BoardsService {
  constructor(
    @InjectRepository(Board) private boardRepository: Repository<Board>
  ) {}
}

References