NestJS -3

sein leeยท2024๋…„ 4์›” 15์ผ
0

nestJS-study

๋ชฉ๋ก ๋ณด๊ธฐ
3/4
post-thumbnail
post-custom-banner

NestJS Pipes

Pipe

  • ํŒŒ์ดํ”„๋Š” @Injectable () ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ํด๋ž˜์Šค
  • data transformation๊ณผ data validation์„ ์œ„ํ•ด์„œ ์‚ฌ์šฉ
  • ํŒŒ์ดํ”„๋Š” ์ปจํŠธ๋กค๋Ÿฌ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๊ธฐ์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋˜๋Š” ์ธ์ˆ˜์— ๋Œ€ํ•ด ์ž‘๋™

Nest๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๊ธฐ ์ง์ „์— ํŒŒ์ดํ”„๋ฅผ ์‚ฝ์ž…ํ•˜๊ณ  ํŒŒ์ดํ”„๋Š” ๋ฉ”์†Œ๋“œ๋กœ ํ–ฅํ•˜๋Š” ์ธ์ˆ˜๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ  ์ด์— ๋Œ€ํ•ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

Data Transformation

์ž…๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ ์›ํ•˜๋Š” ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ (์˜ˆ : ๋ฌธ์ž์—ด์—์„œ ์ •์ˆ˜๋กœ)
์ˆซ์ž๋ฅผ ๋ฐ›๊ธธ ์›ํ•˜๋Š”๋ฐ ๋ฌธ์ž์—ด ํ˜•์‹์œผ๋กœ ์˜จ๋‹ค๋ฉด ํŒŒ์ดํ”„์—์„œ ์ž๋™์œผ๋กœ ์ˆซ์ž๋กœ ๋ฐ”๊ฟ”์ค€๋‹ค.
String to Integer EX) string '7' => Integer 7

Data validation

์ž…๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ ํ‰๊ฐ€ํ•˜๊ณ  ์œ ํšจํ•œ ๊ฒฝ์šฐ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์€ ์ƒํƒœ๋กœ ์ „๋‹ฌํ•˜๋ฉด ๋œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์•„ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
๋งŒ์•ฝ ์ด๋ฆ„์˜ ๊ธธ์ด๊ฐ€ 10์ž ์ดํ•˜์—ฌ์•ผ ํ•˜๋Š”๋ฐ 10์ž ์ด์ƒ ๋˜๋ฉด ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ

PIPE ์‚ฌ์šฉํ•˜๋Š” ๋ฒ•(Binding Pipes)

ํŒŒ์ดํ”„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•(Binding pipes)์€ ์„ธ๊ฐ€์ง€๋กœ ๋‚˜๋ˆ ์งˆ์ˆ˜ ์žˆ๋‹ค.

1. Handler-level Pipes

ํ•ธ๋“ค๋Ÿฌ ๋ ˆ๋ฒจ์—์„œ @UsePipes() ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์ด์šฉํ•œ๋‹ค.
์ด ํŒŒ์ดํ”„๋Š” ๋ชจ๋“  ํŒŒ๋ผ๋ฏธํ„ฐ์— ์ ์šฉ๋œ๋‹ค. (title, description)

2. Parameter-level Pipes

ํŒŒ๋ผ๋ฏธํ„ฐ ๋ ˆ๋ฒจ์˜ ํŒŒ์ดํ”„ ์ด๊ธฐ์— ํŠน์ •ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ์—๊ฒŒ๋งŒ ์ ์šฉ์ด ๋˜๋Š” ํŒŒ์ดํ”„

3. Global-level Pipes

๊ธ€๋กœ๋ฒŒ ํŒŒ์ดํ”„๋กœ์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ ˆ๋ฒจ์˜ ํŒŒ์ด๋ธŒ
ํด๋ผ์ด์–ธํŠธ์—์„œ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์— ์ ์šฉ
๊ฐ€์žฅ ์ƒ๋‹จ ์˜์—ญ์ธ main.ts์— ์ž‘์„ฑ

Built-in Pipes

Nest JS ์— ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด ๋†“์€ 6๊ฐ€์ง€์˜ ํŒŒ์ดํ”„๊ฐ€ ์žˆ๋‹ค.

  • ValidationPipe
  • ParseIntPipe
  • ParseBoolPipe
  • ParseArrayPipe
  • ParseUUIDPipe
  • DefaultValuePipe

ํŒŒ์ดํ”„๋ฅผ ์ด์šฉํ•œ ์œ ํšจ์„ฑ ์ฒดํฌ

๋ชจ๋“ˆ ์„ค์น˜

class-validator , class-transformer
npm install class-validator class-transformer --save

-์ฐธ์กฐ โฌ‡โฌ‡
Documentation ํŽ˜์ด์ง€

ํŒŒ์ดํ”„ ์ƒ์„ฑํ•˜๊ธฐ

ํ˜„์žฌ๋Š” ๊ฒŒ์‹œ๋ฌผ์„ ์ƒ์„ฑํ•  ๋•Œ ์ด๋ฆ„๊ณผ ์„ค๋ช…์— ์•„๋ฌด๋Ÿฐ ๊ฐ’์„ ์ฃผ์ง€ ์•Š์•„๋„ ์•„๋ฌด ๋ฌธ์ œ ์—†์ด ์ƒ์„ฑ์ด ๋œ๋‹ค.=> ํŒŒ์ดํ”„๋กœ ์ˆ˜์ •
<create-board.dto.ts>

import { IsNotEmpty } from "class-validator";

export class createBoardDto{
    @IsNotEmpty() // null ๋ถˆํ—ˆ
    title: string;

    @IsNotEmpty()
    description: string;
}

<controller.ts>

@Post()
    @UsePipes(ValidationPipe) //์œ ํšจ์„ฑ ์ฒดํฌ
    createBoard(
        @Body() createBoardDto: createBoardDto
    ): Board { //return ๊ฐ’์˜ ํƒ€์ž…์€ Board, Board[]๋กœ ์ฃผ๋ฉด ์•ˆ๋จ : service์˜ createBoard์˜ return ๊ฐ’์ด board ํ•˜๋‚˜์ด๊ธฐ ๋•Œ๋ฌธ์—
        return this.boardsService.createBoard(createBoardDto);
    }

<๊ฒฐ๊ณผ>

์—๋Ÿฌ๊ฐ€ ๋‚˜์˜จ๋‹ค!

ํŠน์ • ๊ฒŒ์‹œ๋ฌผ์„ ์ฐพ์„ ๋•Œ ์—†๋Š” ๊ฒฝ์šฐ ๊ฒฐ๊ณผ ๊ฐ’ ์ฒ˜๋ฆฌ


ํ˜„์žฌ ํŠน์ • ๊ฒŒ์‹œ๋ฌผ์„ ID๋กœ ๊ฐ€์ ธ์˜ฌ ๋•Œ ๋งŒ์•ฝ ์—†๋Š” ์•„์ด๋””์˜ ๊ฒŒ์‹œ๋ฌผ์„ ๊ฐ€์ ธ์˜ค๋ ค๊ณ  ํ•œ๋‹ค๋ฉด ๊ฒฐ๊ณผ๊ฐ’์œผ๋กœ ์•„๋ฌด ๋‚ด์šฉ์ด ์—†์ด ๋Œ์•„์˜จ๋‹ค.
=> ๊ฐ€์ ธ์˜ค๋ ค๋Š” ๋‚ด์šฉ์ด ์—†๋‹ค๋Š” ๊ฒฐ๊ณผ๋ฅผ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ณด๋‚ด์ค€๋‹ค.
<service.ts> ๊ธฐ์กด์˜ getBoardId๋ฅผ ์ˆ˜์ •

 getBoardId(id: string): Board{ //๊ฒŒ์‹œ๋ฌผ ํ•˜๋‚˜๋ฅผ return ํ•˜๊ธฐ ๋•Œ๋ฌธ์— Board[] X
        const found = this.boards.find((board)=>board.id === id);

        if(!found){
            throw new NotFoundException(`Can't find Board with id ${id}`);
        }
        return found;
    }

<๊ฒฐ๊ณผ>

์—†๋Š” ๊ฒŒ์‹œ๋ฌผ์„ ์ง€์šฐ๋ ค ํ•  ๋•Œ ๊ฒฐ๊ณผ ๊ฐ’ ์ฒ˜๋ฆฌ

<service.ts>์˜ deleteBoard๋ฅผ ์ˆ˜์ •

deleteBoard(id: string): void{ // return ์„ ๋”ฐ๋กœ ์ฃผ์ง€ ์•Š์•„๋„ ๋˜๊ธฐ ๋•Œ๋ฌธ์— void
       const found = this.getBoardId(id);
       this.boards = this.boards.filter((board) => board.id !==found.id);
   }

์ปค์Šคํ…€ ํŒŒ์ดํ”„๋ฅผ ์ด์šฉํ•œ ์œ ํšจ์„ฑ ์ฒดํฌ

์ง€๊ธˆ๊นŒ์ง€๋Š” NestJS์—์„œ ์ด๋ฏธ ๊ตฌ์„ฑํ•ด๋†“์€ built-in ํŒŒ์ดํ”„๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์•˜๋‹ค.
๋”ฐ๋กœ ์ƒ์„ฑํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” CUSTOM PIPE๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž!

์ปค์Šคํ…€ ํŒŒ์ดํ”„ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•

**PipeTransform์ด๋ž€ ์ธํ„ฐํŽ˜์ด์Šค**๋ฅผ ์ƒˆ๋กญ๊ฒŒ ๋งŒ๋“ค ์ปค์Šคํ…€ ํŒŒ์ดํ”„์— ๊ตฌํ˜„ํ•ด์ค˜์•ผ ํ•œ๋‹ค. 
์ด PipeTransform ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋ชจ๋“  ํŒŒ์ดํ”„์—์„œ ๊ตฌํ˜„ํ•ด์ค˜์•ผ ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค. 
๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ๊ณผ ํ•จ๊ป˜ ๋ชจ๋“  ํŒŒ์ดํ”„๋Š” **transform()** ๋ฉ”์†Œ๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ์ด ๋ฉ”์†Œ๋“œ๋Š” NestJS๊ฐ€  ์ธ์ž(arguments)๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉ๋œ๋‹ค.


<board-status-validation.pipe.ts>

import { ArgumentMetadata, PipeTransform } from "@nestjs/common";

export class BoardStatusValidationPipe implements PipeTransform{
    transform(value: any, metadata: ArgumentMetadata) {
        console.log('value',value)
        console.log('metadata',metadata)
        
        return value;
    }
}

transform() ๋ฉ”์†Œ๋“œ

๋‘๊ฐœ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฐ€์ง€๋Š” ๋ฉ”์†Œ๋“œ
์ฒซ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์ฒ˜๋ฆฌ๊ฐ€ ๋œ ์ธ์ž์˜ ๊ฐ’(value)์ด๋ฉฐ,
๋‘๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์ธ์ž์— ๋Œ€ํ•œ ๋ฉ”ํƒ€ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•œ ๊ฐ์ฒด์ด๋‹ค.

transform()๋ฉ”์†Œ๋“œ์—์„œ Return ๋œ ๊ฐ’์€ Route ํ•ธ๋“ค๋Ÿฌ๋กœ ์ „ํ•ด์ง„๋‹ค.
๋งŒ์•ฝ ์˜ˆ์™ธ(Exception)๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ์— ๋ฐ”๋กœ ์ „ํ•ด์ง„๋‹ค.

์‹ค์ œ๋กœ value ์™€ metadata๊ฐ’ ์ฝ˜์†”๋กœ ์ฐ์–ด๋ณด๊ธฐ

  1. ์ปค์Šคํ…€ ํŒŒ์ดํ”„ ์ƒ์„ฑ
  2. ๊ฒŒ์‹œ๋ฌผ์— ์—…๋ฐ์ดํŠธํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ์— ์ปค์Šคํ…€ ํŒŒ์ดํ”„ ๋„ฃ์–ด์ฃผ๊ธฐ
  3. ํฌ์ŠคํŠธ ๋งจ์œผ๋กœ ์š”์ฒญ ๋ณด๋‚ด๊ธฐ

<controller.ts>์˜ :id/status ๋ถ€๋ถ„ ์ˆ˜์ •
status ๋ฅผ ๋ฐ”๊ฟ€ ๋•Œ ์œ ํšจ์„ฑ ์ฒดํฌ(status ๊ฐ’๋งŒ!)

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

<postman ํ˜ธ์ถœ ์‹œ>

<terminal ์ฝ˜์†”>

์ปค์Šคํ…€ ํŒŒ์ดํ”„๋กœ ์‹ค์ œ ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ

๊ตฌํ˜„ ํ•  ๊ธฐ๋Šฅ : ์ƒํƒœ(Status)๋Š” PUBLIC๊ณผ PRIVATE๋งŒ ์˜ฌ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด์™ธ์˜ ๊ฐ’์ด ์˜ค๋ฉด ์—๋Ÿฌ ์ „์†ก
<board-status-validation.pipe.ts>

import { ArgumentMetadata, BadRequestException, PipeTransform } from "@nestjs/common";
import { BoardStatus } from "../board.model";

export class BoardStatusValidationPipe implements PipeTransform{
    //readonly : ํด๋ž˜์Šค ์™ธ๋ถ€์—์„œ ์ ‘๊ทผ์€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ๋ณ€๊ฒฝ์€ ๋ถˆ๊ฐ€!
    readonly StatusOptions =[
        BoardStatus.PRIVATE,
        BoardStatus.PUBLIC
    ]

    transform(value: any) { // value : ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ status
        value = value.toUpperCase(); //๋Œ€๋ฌธ์ž ๋ณ€ํ™˜

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

    private isStatusValid(status: any){
        const index = this.StatusOptions.indexOf(status); //๋ฐฐ์—ด์•ˆ์— ์žˆ๋Š”์ง€, ์žˆ์œผ๋ฉด ๊ทธ ๋ฐฐ์—ด๋‚ด ์ธ๋ฑ์Šค๊ฐ’
        return index !== -1;
    }
}

<๊ฒฐ๊ณผ1>

<๊ฒฐ๊ณผ2>

PostgresSQL ์„ค์น˜ํ•˜๊ธฐ

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์—ฐ๊ฒฐํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ณด๊ด€, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” Postgres๋ฅผ ์‚ฌ์šฉ

<์„ค์น˜ ๋ชฉ๋ก>
1. PostgresSQL
2. pgAdmin (๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋ณด๋Š” ํˆด(Tool)์ž…๋‹ˆ๋‹ค.)

pgAdmin ์‹คํ–‰
1. Servers > register Server


2. BoardProject ์šฐํด๋ฆญ > Create > database

TypeORM (Object Relational Mapping)์†Œ๊ฐœ

TypeORM

TypeORM์€ node.js์—์„œ ์‹คํ–‰๋˜๊ณ  TypeScript๋กœ ์ž‘์„ฑ๋œ ๊ฐ์ฒด ๊ด€๊ณ„ํ˜• ๋งคํผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

TypeORM์€ MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server, Oracle, SAP Hana ๋ฐ WebSQL๊ณผ ๊ฐ™์€ ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ง€์›ํ•œ๋‹ค.

ORM (Object Relational Mapping) ์ด๋ž€?

๊ฐ์ฒด์™€ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ๋ณ€ํ˜• ๋ฐ ์—ฐ๊ฒฐํ•˜๋Š” ์ž‘์—…

ORM์„ ์ด์šฉํ•œ ๊ฐœ๋ฐœ์€ ๊ฐ์ฒด์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ณ€ํ˜•์— ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

TypeORM vs Pure Javascript

const boards = Board.find({ title: 'Hello' , status: 'PUBLIC' });
db.query('SELECT * FROM boards WHERE title = "Hello" AND status = "PUBLIC" , (err, result) => {
       if(err) { 
          throw new Error('Error')
      }
      boards = result.rows;
})

TypeORM ํŠน์ง•๊ณผ ์ด์ 

  • ๋ชจ๋ธ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ” ์ฒด๊ณ„๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑ
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฐœ์ฒด๋ฅผ ์‰ฝ๊ฒŒ ์‚ฝ์ž…, ์—…๋ฐ์ดํŠธ ๋ฐ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ…Œ์ด๋ธ” ๊ฐ„์˜ ๋งคํ•‘ (์ผ๋Œ€์ผ, ์ผ๋Œ€ ๋‹ค ๋ฐ ๋‹ค ๋Œ€๋‹ค)์„ ๋งŒ๋“ ๋‹ค.
  • ๊ฐ„๋‹จํ•œ CLI ๋ช…๋ น์„ ์ œ๊ณต
  • TypeORM์€ ๊ฐ„๋‹จํ•œ ์ฝ”๋”ฉ์œผ๋กœ ORM ํ”„๋ ˆ์ž„ ์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๋‹ค.
  • TypeORM์€ ๋‹ค๋ฅธ ๋ชจ๋“ˆ๊ณผ ์‰ฝ๊ฒŒ ํ†ตํ•ฉ๋œ๋‹ค.

TypeORM ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ด์šฉํ•˜๊ธฐ

TypeORM์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ์„ค์น˜ํ•ด์•ผํ•˜๋Š” ๋ชจ๋“ˆ๋“ค

@nestjs/typeorm

  • NestJS์—์„œ TypeOrm์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์—ฐ๋™์‹œ์ผœ์ฃผ๋Š” ๋ชจ๋“ˆ

typeorm

  • TypeORM ๋ชจ๋“ˆ

pg

  • Postgres ๋ชจ๋“ˆ
npm install pg typeorm @nestjs/typeorm --save 

database DOC

TypeORM ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์—ฐ๊ฒฐํ•˜๊ธฐ


<typeorm.config.ts>

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

export const typeORMConfig : TypeOrmModuleOptions = {
    //Database Type
    type: 'postgres',
    host: 'localhost',
    port: 5432,
    username:'postgres',
    password: '0121',
    database: 'board-app',
    //์—”ํ‹ฐํ‹ฐ๋Š” ํ•˜๋‚˜์”ฉ ๋„ฃ์„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์ด๋ ‡๊ฒŒ ๋‹ค ํฌํ•จํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค. 
    entities: [__dirname+'/../**/*.entity.{js,ts}'],
    synchronize: true 

}
  • synchronize: true ์ผ๋•Œ : ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋‹ค์‹œ ์‹คํ–‰ํ•  ๋•Œ ์—”ํ‹ฐํ‹ฐ์•ˆ์—์„œ ์ˆ˜์ •๋œ ์ปฌ๋Ÿผ์˜ ๊ธธ์ด ํƒ€์ž… ๋ณ€๊ฒฝ ๊ฐ’๋“ฑ์„ ํ•ด๋‹น ํ…Œ์ด๋ธ”์„ Drop ํ›„ ๋‹ค์‹œ ์ƒ์„ฑํ•ด์คŒ

<app.module.ts> -typeOrm ์‚ฌ์šฉ ์„ค์ •

import { Module } from '@nestjs/common';

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

@Module({
  imports: [
    TypeOrmModule.forRoot(typeORMConfig),
    BoardsModule],

})
export class AppModule {}
  • forRoot์•ˆ์— ๋„ฃ์–ด์ค€ ์„ค์ •(configuration)์€ ๋ชจ๋“  Sub-Module ๋ถ€์ˆ˜์ ์ธ ๋ชจ๋“ˆ๋“ค์— ๋‹ค ์ ์šฉ์ด ๋œ๋‹ค.

๊ฒŒ์‹œ๋ฌผ์„ ์œ„ํ•œ ์—”ํ‹ฐํ‹ฐ(Entity) ์ƒ์„ฑํ•˜๊ธฐ

์™œ Entity๋ฅผ ์ƒ์„ฑํ•ด์•ผํ•˜๋‚˜?

์›๋ž˜ ORM ์—†์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•  ๋•Œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

CREATE TABLE board ( 
   id     INTEGER AUTO_INCREMENT PRIMARY KEY. 
   title  VARCHAR(255)  NOT NULL,
   decsription VARCHAR(255) NOT NULL  
)

ํ•˜์ง€๋งŒ TypeORM์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” Class๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”๋กœ ๋ณ€ํ™˜์‹œ์ผœ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•œ ํ›„ ๊ทธ ์•ˆ์— ์ปฌ๋Ÿผ๋“ค์„ ์ •์˜ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

์—”ํ‹ฐํ‹ฐ ์ƒ์„ฑ ์ฝ”๋“œ


<board.entity.ts>

@Entity()

Entity () ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํด๋ž˜์Šค๋Š” Board ํด๋ž˜์Šค๊ฐ€ ์—”ํ‹ฐํ‹ฐ์ž„์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐ ์‚ฌ์šฉ (sql ๋ฌธ์˜ CREATE TABLE board ๋ถ€๋ถ„)

@PrimaryGeneratedColumn()

PrimaryGeneratedColumn () ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํด๋ž˜์Šค๋Š” id ์—ด์ด Board ์—”ํ„ฐํ‹ฐ์˜ ๊ธฐ๋ณธ ํ‚ค ์—ด์ž„์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐ ์‚ฌ์šฉ

@Column()

Column () ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํด๋ž˜์Šค๋Š” Board ์—”ํ„ฐํ‹ฐ์˜ title ๋ฐ description๊ณผ ๊ฐ™์€ ๋‹ค๋ฅธ ์—ด์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐ ์‚ฌ์šฉ

Repository ์ƒ์„ฑํ•˜๊ธฐ

Repository

๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋Š” ์—”ํ„ฐํ‹ฐ ๊ฐœ์ฒด์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋ฉฐ ์—”ํ‹ฐํ‹ฐ ์ฐพ๊ธฐ, ์‚ฝ์ž…, ์—…๋ฐ์ดํŠธ, ์‚ญ์ œ ๋“ฑ์„ ์ฒ˜๋ฆฌ
Repository๋ž€?

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๊ด€๋ จ ๋œ ์ผ(INSERT, FIND, DELETE..๋“ฑ๋“ฑ)์€ ์„œ๋น„์Šค์—์„œ ํ•˜๋Š”๊ฒŒ ์•„๋‹Œ Repository์—์„œ ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
์ด๊ฒƒ์„ Repository Pattern ์ด๋ผ๊ณ ๋„ ํ•œ๋‹ค.

Repository ์ƒ์„ฑํ•˜๊ธฐ

  1. ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ํŒŒ์ผ ์ƒ์„ฑํ•˜๊ธฐ

  2. ์ƒ์„ฑํ•œ ํŒŒ์ผ์— ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์œ„ํ•œ ํด๋ž˜์Šค ์ƒ์„ฑํ•˜๊ธฐ (BoardRepository)
    <board.repository.ts>

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

@EntityRepository(Board)
export class BoardRepository extends Repository<Board>{
    
}
  • ์ƒ์„ฑ ์‹œ Repository ํด๋ž˜์Šค๋ฅผ Extends ํ•ด์ค๋‹ˆ๋‹ค. (Find, Insert, Delete ๋“ฑ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ปจํŠธ๋กค ํ•ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)

@EntityRepository()

  • ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉ์ž ์ •์˜(CUSTOM) ์ €์žฅ์†Œ๋กœ ์„ ์–ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ
    ์‚ฌ์šฉ์ž ์ง€์ • ์ €์žฅ์†Œ๋Š” ์ผ๋ถ€ ํŠน์ • ์—”ํ„ฐํ‹ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ฑฐ๋‚˜ ์ผ๋ฐ˜ ์ €์žฅ์†Œ ์ผ ์ˆ˜ ์žˆ๋‹ค.
  1. ์ƒ์„ฑํ•œ Repository๋ฅผ ๋‹ค๋ฅธ๊ณณ์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ์œ„ํ•ด์„œ(Injectable) board.module์—์„œ import ํ•ด์ค€๋‹ค.
    < board.module.ts>
import { Module } from '@nestjs/common';
import { BoardsController } from './boards.controller';
import { BoardsService } from './boards.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { BoardRepository } from './board.repository';

@Module({
  imports:[TypeOrmModule.forFeature([BoardRepository])],
  controllers: [BoardsController],
  providers: [BoardsService]
})
export class BoardsModule {}
profile
๊ฐœ๋ฐœ๊ฐ์ž
post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€