# Providers

## Providers

공급자는 Nest의 기본 개념입니다. 많은 기본 Nest 클래스는 서비스, 저장소, 팩토리, 헬퍼 등 공급자로 취급될 수 있습니다. 공급자의 주요 아이디어는 의존성을 **주입** 할 수 있다는 것입니다. 즉, 개체가 서로 다양한 관계를 만들 수 있으며 개체의 "배선"기능을 Nest 런타임 시스템에 크게 위임 할 수 있습니다. 공급자는 단순히 `@Injectable()`데코레이터로 주석이 달린 클래스입니다.

![](https://docs.nestjs.com/assets/Components_1.png)

&#x20;이전 장에서 우리는 간단한 `CatsController`를 만들었습니다. 컨트롤러는 HTTP 요청을 처리하고 더 복잡한 작업을 **공급자**에게 위임해야 합니다. 공급자는 클래스 선언 앞에 `@Injectable()` 데코레이터가 있는 일반 JavaScript 클래스입니다.

> info **힌트** Nest를 사용하면 좀 더 다양한 방법으로 종속성을 디자인하고 구성 할 수 있으므로 [SOLID](https://en.wikipedia.org/wiki/SOLID) 원칙을 따르는 것이 좋습니다.

## Services

간단한 `CatsService`를 만들어 봅시다. 이 서비스는 데이터 저장 및 검색을 담당하며 `CatsController`에서 사용하도록 설계되었으므로 공급자로 정의하는 것이 좋습니다. 따라서 클래스를 `@Injectable()`으로 장식합니다.

```typescript
@@filename(cats.service)
import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';

@Injectable()
export class CatsService {
  private readonly cats: Cat[] = [];

  create(cat: Cat) {
    this.cats.push(cat);
  }

  findAll(): Cat[] {
    return this.cats;
  }
}
@@switch
import { Injectable } from '@nestjs/common';

@Injectable()
export class CatsService {
  constructor() {
    this.cats = [];
  }

  create(cat) {
    this.cats.push(cat);
  }

  findAll() {
    return this.cats;
  }
}
```

> info **힌트** CLI를 사용하여 서비스를 만들려면 간단히 `$nest g service cats` 명령을 실행하십시오.

우리의 `CatsService`는 하나의 속성과 두 개의 메소드를 가진 기본 클래스입니다. 유일한 새로운 기능은`@Injectable()` 데코레이터를 사용한다는 것입니다. `@Injectable()` 데코레이터는 메타 데이터를 첨부하여 이 클래스가 Nest 공급자라는 것을 Nest에게 알려줍니다. 그건 그렇고, 이 예제는 `Cat` 인터페이스도 사용하는데, 아마도 다음과 같이 보일 것입니다:

```typescript
export interface Cat {
  name: string;
  age: number;
  breed: string;
}
```

Cat를 검색하는 서비스 클래스가 생겼으니 `CatsController` 안에서 사용하자:

```typescript
@@filename(cats.controller)
import { Controller, Get, Post, Body } from '@nestjs/common';
import { CreateCatDto } from './dto/create-cat.dto';
import { CatsService } from './cats.service';
import { Cat } from './interfaces/cat.interface';

@Controller('cats')
export class CatsController {
  constructor(private readonly catsService: CatsService) {}

  @Post()
  async create(@Body() createCatDto: CreateCatDto) {
    this.catsService.create(createCatDto);
  }

  @Get()
  async findAll(): Promise<Cat[]> {
    return this.catsService.findAll();
  }
}
@@switch
import { Controller, Get, Post, Body, Bind, Dependencies } from '@nestjs/common';
import { CatsService } from './cats.service';

@Controller('cats')
@Dependencies(CatsService)
export class CatsController {
  constructor(catsService) {
    this.catsService = catsService;
  }

  @Post()
  @Bind(Body())
  async create(createCatDto) {
    this.catsService.create(createCatDto);
  }

  @Get()
  async findAll() {
    return this.catsService.findAll();
  }
}
```

`CatsService`는 클래스 생성자를 통해 **주입**됩니다. `private readonly` 구문의 사용에 주목하십시오. 이 속기는 우리가 동일한 위치에서 즉시 `catsService` 멤버를 선언하고 초기화 할 수있게 한다.

## Dependency injection

Nest는 일반적으로 **종속 주입**으로 알려진 강력한 디자인 패턴을 중심으로 구축되었습니다. 공식 [Angular](https://angular.io/guide/dependency-injection) 문서에서 이 개념에 대한 훌륭한 기사를 읽는 것이 좋습니다.

Nest의 TypeScript 기능 덕분에 종속성은 유형별로 해결되기 때문에 종속성을 관리하기가 매우 쉽습니다. 아래 예제에서 Nest는 `CatsService`의 인스턴스를 생성하고 반환함으로써 (또는 일반적인 경우 싱글 톤의 경우 이미 다른 곳에 요청 된 경우 기존 인스턴스를 반환하여) `catsService`를 해결합니다. 이 종속성은 해결되어 컨트롤러의 생성자에게 전달되거나 표시된 속성에 할당됩니다.

```typescript
constructor(private readonly catsService: CatsService) {}
```

## Scopes

공급자는 일반적으로 응용 프로그램 수명주기와 동기화 된 수명 ( `범위`)을 갖습니다. 응용 프로그램이 부트 스트랩 될 때 모든 종속성을 해결해야 하므로 모든 공급자를 인스턴스화 해야 합니다. 마찬가지로 응용 프로그램이 종료되면 각 공급자가 삭제됩니다. 그러나 공급자의 수명을 **요청 범위**로 만드는 방법도 있습니다. 이러한 기술에 대한 자세한 내용은 [여기](https://app.gitbook.com/fundamentals/injection-scopes)를 참조하십시오.

## Custom providers

Nest에는 공급자간 관계를 해결하는 기본 제공 제어 역전 ( "IoC") 컨테이너가 있습니다. 이 기능은 위에서 설명한 종속성 주입 기능의 기초가 되지만 실제로 지금까지 설명한 것보다 훨씬 강력합니다. `@Injectable()` 데코레이터는 빙산의 일각 일 뿐이며 공급자를 정의하는 유일한 방법은 아닙니다. 실제로 일반 값, 클래스 및 비동기 또는 동기 팩토리를 사용할 수 있습니다. 더 많은 예가 [여기](https://app.gitbook.com/fundamentals/dependency-injection)에 제공됩니다 .

## Optional providers

때때로, 반드시 해결 될 필요가 없는 종속성이 있을 수 있습니다. 예를 들어 클래스는 **구성 객체**에 의존할 수 있지만 전달되지 않은 경우 기본값을 사용해야합니다. 이러한 경우 구성 공급자가 없으면 오류가 발생하지 않으므로 종속성이 선택 사항이됩니다.

공급자가 선택적임을 나타내려면 `constructor` 서명에 `@Optional()` 데코레이터를 사용하십시오.

```typescript
import { Injectable, Optional, Inject } from '@nestjs/common';

@Injectable()
export class HttpService<T> {
  constructor(
    @Optional() @Inject('HTTP_OPTIONS') private readonly httpClient: T
  ) {}
}
```

위의 예에서 우리는 커스텀 제공자를 사용하고 있는데, 이것이 우리가 `HTTP_OPTIONS` 커스텀 **토큰**을 포함하는 이유입니다. 이전 예제는 생성자에서 클래스를 통한 종속성을 나타내는 생성자 기반 주입을 보여줍니다. 사용자 지정 공급자 및 관련 토큰에 대한 자세한 내용은 [여기](https://app.gitbook.com/fundamentals/custom-providers)를 참조하십시오.

## Property-based injection

우리가 지금까지 사용한 기술은 생성자 메서드를 통해 공급자가 주입되므로 constuctor 기반 주입이라고 합니다. 매우 특정한 경우에는 **속성 기반 주입**이 유용 할 수 있습니다. 예를 들어 최상위 클래스가 하나 이상의 공급자에 의존하는 경우 생성자의 하위 클래스에서 `super()`를 호출하여 모든 공급자를 전달하는 것은 매우 지루할 수 있습니다. 이를 피하기 위해 속성 레벨에서 `@Inject()`데코레이터를 사용할 수 있습니다.

```typescript
import { Injectable, Inject } from '@nestjs/common';

@Injectable()
export class HttpService<T> {
  @Inject('HTTP_OPTIONS')
  private readonly httpClient: T;
}
```

> warning **경고** 클래스가 다른 제공자를 확장하지 않는 경우 항상 **생성자 기반** 주입을 사용하는 것이 좋습니다.

## Provider registration

이제 우리는 공급자 (CatsService)를 정의했고, 그 서비스의 소비자 (CatsController)를 가지고 있으므로, 주입을 수행할 수 있도록 Nest에 서비스를 등록해야 합니다. 모듈 파일 (`app.module.ts`)을 편집하고 서비스를 `@Module()` 데코레이터의 `providers` 배열에 추가하면 됩니다.

```typescript
@@filename(app.module)
import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';
import { CatsService } from './cats/cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService],
})
export class AppModule {}
```

Nest는 이제 `CatsController` 클래스의 의존성을 해결할 수 있습니다.

디렉토리 구조는 다음과 같습니다.

* src
  * cats
    * dto
      * create-cat.dto.ts
    * interfaces
      * cat.interface.ts
    * cats.service.ts
    * cats.controller.ts
  * app.module.ts
  * main.ts


---

# 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/overview/untitled-4.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.
