# CRUD

## CRUD

### This chapter applies only to TypeScript

[CRUD](https://github.com/nestjsx/crud) 패키지 (`@nestjsx/crud`)를 사용하면 CRUD 컨트롤러 및 서비스를 쉽게 만들 수 있으며 RESTful API를 위한 다양한 기능을 즉시 사용할 수 있습니다.

* 데이터베이스에 관계없이 확장 가능한 CRUD 컨트롤러
* 필터링, 페이지 매김, 정렬, 관계, 중첩 관계, 캐시 등을 사용하여 쿼리 문자열 구문 분석
* 프론트 엔드 사용을 위한 쿼리 빌더가 있는 프레임 워크에 구애받지 않는 패키지
* 쿼리, 경로 매개 변수 및 DTO 유효성 검사
* 컨트롤러 메소드를 쉽게 재정의
* 작지만 강력한 구성 (글로벌 구성 포함)
* 추가 헬퍼 데코레이터
* Swagger 다큐먼트

> warning **알림** 지금까지`@nestjsx/crud`는 `TypeORM` 만 지원하지만 `Sequelize` 및 `Mongoose`와 같은 다른 ORM도 가까운 시일 내에 포함될 예정입니다. 따라서 이 기사에서는 `TypeORM`을 사용하여 CRUD 컨트롤러 및 서비스를 작성하는 방법에 대해 설명합니다. `@nestjs/typeorm` 패키지를 이미 성공적으로 설치하고 설정했다고 가정합니다. 자세한 내용은 [여기](https://app.gitbook.com/techniques/sql)를 참조하십시오.

## Getting started

CRUD 기능 생성을 시작하려면 필요한 모든 종속성을 설치해야 합니다.

```bash
npm i --save @nestjsx/crud @nestjsx/crud-typeorm class-transformer class-validator
```

프로젝트에 이미 일부 **엔터티**가 있다고 가정합니다.

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

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

  @Column()
  name: string;

  @Column({ type: 'number' })
  power: number;
}
```

우리가 해야 할 첫번째 단계는 **service**를 만드는 것입니다.

```typescript
@@filename(heroes.service)
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { TypeOrmCrudService } from '@nestjsx/crud-typeorm';
import { Hero } from './hero.entity';

@Injectable()
export class HeroesService extends TypeOrmCrudService<Hero> {
  constructor(@InjectRepository(Hero) repo) {
    super(repo);
  }
}
```

서비스가 완료되었으므로 **컨트롤러**를 만들어 봅시다 :

```typescript
@@filename(heroes.controller)
import { Controller } from '@nestjs/common';
import { Crud } from '@nestjsx/crud';
import { Hero } from './hero.entity';
import { HeroesService } from './heroes.service';

@Crud({
  model: {
    type: Hero,
  },
})
@Controller('heroes')
export class HeroesController {
  constructor(public service: HeroesService) {}
}
```

마지막으로 **모듈**에 모든 것을 연결해야합니다.

```typescript
@@filename(heroes.module)
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';

import { Hero } from './hero.entity';
import { HeroesService } from './heroes.service';
import { HeroesController } from './heroes.controller';

@Module({
  imports: [TypeOrmModule.forFeature([Hero])],
  providers: [HeroesService],
  controllers: [HeroesController],
})
export class HeroesModule {}
```

> warning **알림** `HeroesModule`을 루트 `ApplicationModule`로 가져 오는 것을 잊지 마십시오.

이후에 Nest 애플리케이션에는 다음과 같이 새로 작성된 엔드 포인트가 있습니다.

* `GET /heroes` - get many heroes.
* `GET /heroes/:id` - get one hero.
* `POST /heroes/bulk` - create many heroes.
* `POST /heroes` - create one hero.
* `PATCH /heroes/:id` - update one hero.
* `PUT /heroes/:id` - replace one hero.
* `DELETE /heroes/:id` - delete one hero.

## Filtering and pagination

[CRUD](https://github.com/nestjsx/crud) provides rich tools for filtering and pagination. Example request:

> info **Request** GET /heroes?**select**=name&**filter**=power||gt||90&**sort**=name,ASC&**page**=1&**limit**=3

이 예에서는 히어로 목록을 요청하고 히어로의 `파워`가 90보다 큰 `name`속성만 선택하고 1 페이지 내에서 결과 제한을 3으로 설정했습니다. `ASC` 순서로 `name`으로 정렬됩니다.

응답 객체는 다음과 비슷합니다.

```javascript
{
  "data": [
    {
      "id": 2,
      "name": "Batman"
    },
    {
      "id": 4,
      "name": "Flash"
    },
    {
      "id": 3,
      "name": "Superman"
    }
  ],
  "count": 3,
  "total": 14,
  "page": 1,
  "pageCount": 5
}
```

> warning **알림** 기본 열은 요청 여부에 관계없이 리소스 응답 개체에 유지됩니다. 우리의 경우에는 `id` 열입니다.

쿼리 매개 변수 및 필터 연산자의 전체 목록은 프로젝트의 [Wiki](https://github.com/nestjsx/crud/wiki/Requests)에서 찾을 수 있습니다.

## Relations

언급할 가치가 있는 또 다른 기능은 "관계"입니다. CRUD 제어기에서 API 호출 내에서 페치할 수 있는 엔티티 관계 목록을 지정할 수 있습니다.

```typescript
@Crud({
  model: {
    type: Hero,
  },
  join: {
    profile: {
      exclude: ['secret'],
    },
    faction: {
      eager: true,
      only: ['name'],
    },
  },
})
@Controller('heroes')
export class HeroesController {
  constructor(public service: HeroesService) {}
}
```

`@Crud()`데코레이터 옵션에서 허용된 관계를 지정한 후 다음과 같은 요청을 할 수 있습니다.

> info **Request** GET /heroes/25?**join**=profile||address,bio

응답에는 `address` 및 `bio` 열이 선택되고 결합된 프로파일을 가진 hero 객체가 포함됩니다.

또한 응답에는 `eager: true`로 설정되어 있으므로 모든 응답에서 지속되므로 `name` 열이 선택된 `faction` 오브젝트가 포함됩니다.

프로젝트의 [WiKi](https://github.com/nestjsx/crud/wiki/Controllers#join)에서 관계에 대한 자세한 정보를 찾을 수 있습니다.

## Path params validation

기본적으로 [CRUD](https://github.com/nestjsx/crud)는 이름이 `id`인 슬러그를 생성하고 `number`로 유효성을 검사합니다.

그러나 이 동작을 변경할 가능성이 있습니다. 엔티티에 기본 열 `_id` (UUID 문자열)가 있고 이를 엔드 포인트의 슬러그로 사용해야 한다고 가정하십시오. 이 옵션을 사용하면 다음과 같은 작업을 쉽게 수행할 수 있습니다.

```typescript
@Crud({
  model: {
    type: Hero,
  },
  params: {
    _id: {
      field: '_id',
      type: 'uuid',
      primary: true,
    },
  },
})
@Controller('heroes')
export class HeroesController {
  constructor(public service: HeroesService) {}
}
```

더 많은 params 옵션은 프로젝트의 [Wiki](https://github.com/nestjsx/crud/wiki/Controllers#params)를 참조하십시오.

## Request body validation

요청 본문 유효성 검사는 각 POST, PUT, PATCH 요청에 Nest `ValidationPipe`를 적용하여 기본적으로 수행됩니다. 우리는 `@Crud()`데코레이터 옵션의 `model.type`을 유효성 검사 규칙을 설명하는 DTO로 사용합니다.

이를 제대로 수행하기 위해 [validation groups](https://github.com/typestack/class-validator#validation-groups)를 사용합니다.

```typescript
@@filename(hero.entity)
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
import { IsOptional, IsDefined, IsString, IsNumber } from 'class-validator';
import { CrudValidationGroups } from '@nestjsx/crud';

const { CREATE, UPDATE } = CrudValidationGroups;

@Entity()
export class Hero {
  @IsOptional({ always: true })
  @PrimaryGeneratedColumn()
  id: number;

  @IsOptional({ groups: [UPDATE] })
  @IsDefined({ groups: [CREATE] })
  @IsString({ always: true })
  @Column()
  name: string;

  @IsOptional({ groups: [UPDATE] })
  @IsDefined({ groups: [CREATE] })
  @IsNumber({}, { always: true })
  @Column({ type: 'number' })
  power: number;
}
```

> warning **알림** `create` 및`update` 조치에 대해 별도의 DTO 클래스를 완전히 지원하는 것은 다음 [CRUD](https://github.com/nestjsx/crud) 릴리스의 주요 우선 순위 중 하나입니다.

## Routes options

`@Crud()`데코레이터를 적용하여 생성되는 특정 경로만 비활성화하거나 활성화 할 수 있습니다.

```typescript
@Crud({
  model: {
    type: Hero,
  },
  routes: {
    only: ['getManyBase'],
    getManyBase: {
      decorators: [
        UseGuards(HeroAuthGuard)
      ]
    }
  }
})
@Controller('heroes')
export class HeroesController {
  constructor(public service: HeroesService) {}
}
```

또한 메소드 데코레이터를 특정 경로 `decorators` 배열에 전달하여 모든 메소드 데코레이터를 적용할 수 있습니다. 기본 메소드를 재 정의하지 않고 일부 데코레이터를 추가할 때 편리합니다.

## Documentation

이 챕터의 예는 [CRUD](https://github.com/nestjsx/crud) 기능 중 일부만 다룹니다. 프로젝트의 [Wiki](https://github.com/nestjsx/crud/wiki/Home) 페이지에서 더 많은 사용 질문에 대한 답변을 찾을 수 있습니다.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jakekwak.gitbook.io/nestjs/recipes/untitled-8.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
