반응형

nest.js

 

이번 시간에는 TypeORM 모듈을 이용해서 DB을 연결해서 간단한 게시판(Board 모듈) CRUD를 진행해 보도록 하겠습니다.

 

준비사항 : mysql DB

간단하게 docker를 이용해서 local에서 mysql 사용하고 싶으시다면 참고 하시면 좋을 것 같습니다.

docker-compose.yml

version: '3.1'

services:
  db:
    image: mysql
    restart: always
    command: --lower_case_table_names=1 # 대소문자 구분
    container_name: mysql-db
    environment:
      - MYSQL_DATABASE=test
      - MYSQL_ROOT_PASSWORD=1234
      - TZ=Asia/Seoul
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
    volumes:
      - ./db:/var/lib/mysql # db 볼륨 처리
    ports:
      - 3306:3306

      # docker-compose up -d

 

1. TypeORM 모듈 install

  - 저는 mysql db를 사용하도록 하겠습니다.

  - mysql과 typeorm 모듈을 설치합니다.

npm install mysql2 typeorm @nestjs/typeorm

 

2. TypeORM config 설정

config.typeorm.ts

import { TypeOrmModuleOptions } from "@nestjs/typeorm";

export const typeORMConfig : TypeOrmModuleOptions = {
    type: 'mysql',
    host: 'localhost',
    port: 3306,
    username: 'root',
    password: '1234',
    database: 'test',
    entities: [__dirname+ '/../**/*.entity.{js,ts}'],
    synchronize:true
}

 

app.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { typeORMConfig } from './configs/config.typeorm';

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

 

3. board 모듈을 만들어 보도록 하겠습니다.

board 모듈 구조는 아래 그림과 같습니다.

board 모듈 구조

board.entity.ts

  - DB 테이블이 되는 Entity 객체

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

@Entity()
export class Board extends BaseEntity {

    @PrimaryGeneratedColumn()
    id:number;

    @Column()
    title:string;

    @Column()
    description:string;

    @Column()
    status:BoardStatus;
}

 

board.repository.ts

import { Repository } from "typeorm";
import { Board } from "./board.entity";

export class BoardRepository extends Repository<Board> {
}

 

boards.controller.ts

import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, UsePipes, ValidationPipe } from '@nestjs/common';
import { BoardsService } from './boards.service';
import { BoardStatus } from './board-status.enum';
import { CreateBoardDto } from './dto/create-board.dto';
import { Board } from './board.entity';

@Controller('boards')
export class BoardsController {
    constructor( private boardsService : BoardsService) {} 
    // nest에서는 boardsService 인스턴스를 프로퍼티라고 부르는 것 같다

    @Get('/:id')
    getBoardById(@Param('id') id:number) : Promise<Board> {
        return this.boardsService.getBoardById(id);
    }

    @Post()
    @UsePipes(ValidationPipe)
    createBoard(@Body() createBoardDto: CreateBoardDto) : Promise<Board> {
        return this.boardsService.createBoard(createBoardDto);
    }

    @Patch('/:id/status')
    updateBoardStatus(
        @Param('id', ParseIntPipe) id: number,
        @Body('status') status : BoardStatus
    ) {
        return this.boardsService.updateBoardStatus(id, status);
    }

    @Delete('/:id')
    deleteBoard(@Param('id', ParseIntPipe) id: number) {
        return this.boardsService.deleteBoard(id);
    }

}

  - validationPipe를 사용하기 위해서는 아래와 같이 npm install이 필요합니다.

설치하게되면 기본적인 validation 체크를 위한 데코레이터를 사용할 수 있습니다.

npm install class-validator class-transformer --save

 

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() // nest js 어디에서나 사용할 수 있게 해준다
export class BoardsService {

    constructor(
        @InjectRepository(Board)
        private boardRepository : Repository<Board>,
    ){}

    async getBoardById(id: number): Promise <Board> {
        const found = await this.boardRepository.findOneBy({id});
        if(!found) {
            throw new NotFoundException(`Can't find Board with id ${id}`);
        }
        return found;
    }

    async createBoard(createBoardDto : CreateBoardDto) : Promise<Board> {
        const {title, description} = createBoardDto;

        const board = this.boardRepository.create({
            title,
            description,
            status: BoardStatus.PUBLIC
        })

        await this.boardRepository.save(board);
        return board;
    }

    async updateBoardStatus(id:number, status: BoardStatus) : Promise<Board> {
        const board = await this.getBoardById(id);
        
            board.status = status;
            await this.boardRepository.save(board);

            return board;
    }

    async deleteBoard(id:number) : Promise<void> {
        const result = await this.boardRepository.delete(id);

        if(result.affected === 0 ) {
            throw new NotFoundException(`Can't find Board with id ${id}`);
        }
    }

}

 

create-board.dto.ts

  - dto class

import { IsNotEmpty } from "class-validator";

export class CreateBoardDto{
    @IsNotEmpty()
    title:string;

    @IsNotEmpty()
    description:string;
}

 

board-status.enum.ts

  - BoardStatus를 상수로 쓰기 위한 enum

// 게시판 모델 정의
// interface : 변수의 타입만의 체크한다.
// classes   : 변수의 타입도 체크하고 인스턴스 생성할 수 있다.

// export interface Board {

//     id: string;
//     title: string;
//     description: string;
//     status: BoardStatus

// }

export enum BoardStatus {
    PUBLIC = 'PUBLIC',
    PRIVATE = 'PRIVATE'
}

 

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 {}

 

app.module.ts

  - imports에 BoardsModule을 추가합니다.

import { Module } from '@nestjs/common';
import { BoardsModule } from './boards/boards.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { typeORMConfig } from './configs/config.typeorm';

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

 

참조

- 따라하며 배우는 NestJS

728x90
반응형

'NestJS' 카테고리의 다른 글

[Nest.js] PIPE  (0) 2023.08.27
[Nest.js] 기본 파일 구조 및 요청 흐름  (2) 2023.08.20
[Nest.js] Quick Start!  (0) 2023.08.15

+ Recent posts