> For the complete documentation index, see [llms.txt](https://jakekwak.gitbook.io/nestjs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jakekwak.gitbook.io/nestjs/microservices/untitled-4.md).

# gRPC

## gRPC

[gRPC](https://github.com/grpc/grpc-node)는 고성능 오픈 소스 범용 RPC 프레임 워크입니다.

## Installation

시작하기 전에 필요한 패키지를 설치해야합니다.

```bash
$ npm i --save grpc @grpc/proto-loader
```

## Transporter

**gRPC** 전송기로 전환하려면 `createMicroservice()`메소드에 전달된 옵션 객체를 수정해야 합니다.

```typescript
@@filename(main)
const app = await NestFactory.createMicroservice(ApplicationModule, {
  transport: Transport.GRPC,
  options: {
    package: 'hero',
    protoPath: join(__dirname, 'hero/hero.proto'),
  },
});
```

> info **힌트** `join()`함수는 `path` 패키지에서 가져오고 `Transport` 열거는 `@nestjs/microservices`에서 온 것입니다.

## Options

전송기 동작을 결정하는 사용 가능한 옵션이 많이 있습니다.

| `url`         | Connection url                                                                                                           |
| ------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `protoLoader` | NPM 패키지 이름 (다른 프로토 로더를 사용하려는 경우)                                                                                         |
| `protoPath`   | `.proto` 파일의 절대 (또는 루트 디렉토리에 대한) 경로                                                                                      |
| `loader`      | `@grpc/proto-loader`옵션. [여기](https://github.com/grpc/grpc-node/tree/master/packages/grpc-protobufjs#usage).에 잘 설명되어 있습니다 |
| `package`     | Protobuf package name                                                                                                    |
| `credentials` | Server credentials ([read more](https://grpc.io/grpc/node/grpc.ServerCredentials.html))                                  |

## Overview

일반적으로 `package` 속성은 [protobuf](https://developers.google.com/protocol-buffers/docs/proto) 패키지 이름을 설정하고 `protoPath`는`.proto` 정의 파일의 경로입니다. `hero.proto` 파일은 프로토콜 버퍼 언어를 사용하여 구성됩니다.

```typescript
syntax = "proto3";

package hero;

service HeroService {
  rpc FindOne (HeroById) returns (Hero) {}
}

message HeroById {
  int32 id = 1;
}

message Hero {
  int32 id = 1;
  string name = 2;
}
```

위의 예에서, 우리는 `HeroById`를 입력으로 예상하고 `Hero` 메시지를 리턴하는 `FindOne()` gRPC 핸들러를 노출하는 `HeroService`를 정의했습니다. 이 프로토 타입 정의를 충족시키는 핸들러를 정의하려면 `@GrpcMethod()` 데코레이터를 사용해야합니다. 이전에 알려진 `@MessagePattern()`은 더 이상 유용하지 않습니다.

```typescript
@@filename(hero.controller)
@GrpcMethod('HeroService', 'FindOne')
findOne(data: HeroById, metadata: any): Hero {
  const items = [
    { id: 1, name: 'John' },
    { id: 2, name: 'Doe' },
  ];
  return items.find(({ id }) => id === data.id);
}

```

> info **힌트** `@GrpcMethod()`데코레이터는 `@nestjs/microservices` 패키지에서 가져옵니다.

`HeroService`는 서비스 이름인 반면, `FindOne`은 `FindOne()` gRPC 핸들러를 가리킵니다. 해당하는 `findOne()` 메소드는 두가지 인수, 즉 호출자로부터 전달된 `data`와 gRPC 요청의 메타 데이터를 저장하는 `metadata`를 취합니다.

또한, `FindOne`은 실제로 여기서 중복됩니다. `@GrpcMethod()`에 두 번째 인수를 전달하지 않으면 Nest는 자동으로 첫 번째 문자 (예 :`findOne`->`FindOne`)와 함께 메소드 이름을 사용합니다.

```typescript
@@filename(hero.controller)
@Controller()
export class HeroService {
  @GrpcMethod()
  findOne(data: HeroById, metadata: any): Hero {
    const items = [
      { id: 1, name: 'John' },
      { id: 2, name: 'Doe' },
    ];
    return items.find(({ id }) => id === data.id);
  }
}

```

마찬가지로 인수를 전달하지 못할 수도 있습니다. 이 경우 Nest는 클래스 이름을 사용합니다.

```typescript
@@filename(hero.controller)
@Controller()
export class HeroService {
  @GrpcMethod()
  findOne(data: HeroById, metadata: any): Hero {
    const items = [
      { id: 1, name: 'John' },
      { id: 2, name: 'Doe' },
    ];
    return items.find(({ id }) => id === data.id);
  }
}

```

## Client

클라이언트 인스턴스를 만들려면 `@Client()`데코레이터를 사용해야 합니다.

```typescript
@Client({
  transport: Transport.GRPC,
  options: {
    package: 'hero',
    protoPath: join(__dirname, 'hero/hero.proto'),
  },
})
client: ClientGrpc;
```

이전 예와 비교하여 약간의 차이가 있습니다. `ClientProxy` 클래스 대신, `getService()` 메소드를 제공하는 `ClientGrpc`를 사용합니다. `getService()`제네릭 메서드는 서비스 이름을 인수로 사용하고 가능한 경우 해당 인스턴스를 반환합니다.

```typescript
@@filename(hero.controller)
onModuleInit() {
  this.heroService = this.client.getService<HeroService>('HeroService');
}

```

`heroService` 객체는 `.proto` 파일 내에 정의된 것과 동일한 메소드 세트를 노출합니다. 모든 규칙은 **소문자** (자연 규칙을 따르기 위해)입니다. 기본적으로 gRPC `HeroService` 정의에는 `FindOne()`함수가 포함되어 있습니다. `heroService` 인스턴스는 `findOne()`메소드를 제공한다는 의미입니다.

```typescript
interface HeroService {
  findOne(data: { id: number }): Observable<any>;
}
```

모든 서비스 메소드는 `Observable`을 리턴합니다. Nest는 [RxJS](https://github.com/reactivex/rxjs) 스트림을 지원하고 잘 작동하므로 HTTP 처리기 내에서도 반환할 수 있습니다.

```typescript
@@filename(hero.controller)
@Get()
call(): Observable<any> {
  return this.heroService.findOne({ id: 1 });
}

```

전체 작업 예는 [여기](https://github.com/nestjs/nest/tree/master/sample/04-grpc)에서 확인할 수 있습니다.

## gRPC Streaming

GRPC 자체는 `스트림`으로 알려진 롱텀 라이브 연결을 지원합니다. 스트림은 채팅, 관찰 또는 청크 데이터 전송과 같은 서비스 사례에 매우 유용한 도구가 될 수 있습니다. 공식 문서 ([여기](https://grpc.io/docs/guides/concepts/))에서 자세한 내용을 확인할 수 있습니다.

Nest는 두 가지 방법으로 GRPC 스트림 핸들러를 지원합니다.

* RxJS `Subject` + `Observable` 핸들러: Controller 메소드 내에서 바로 응답을 쓰거나 `Subject`/`Observable` 소비자에게 전달하는 데 유용 할 수 있습니다
* 순수 GRPC 호출 스트림 핸들러: 노드 표준 `Duplex` 스트림 핸들러에 대한 나머지 디스패치를 처리하는 일부 실행기에 전달하는 데 유용 할 수 있습니다.

## Subject strategy

`@GrpcStreamMethod()`데코레이터는 함수 매개 변수를 RxJS `Observable`로 제공합니다.

```typescript
// Set decorator with selecting a Service definition from protobuf package
// the string is matching to: package proto_example.orders.OrdersService
@GrpcStreamMethod('orders.OrderService')
handleStream(messages: Observable<any>): Observable<any> {
  const subject = new Subject();
  messages.subscribe(message => {
    console.log(message);
    subject.next({
      shipmentType: {
        carrier: 'test-carrier',
      },
    });
  });
  return subject.asObservable();
}
```

`@GrpcStreamMethod()`데코레이터와의 전이중 상호 작용을 지원하려면 컨트롤러 메소드에서 RxJS 'Observable'을 반환해야 합니다.

## Pure GRPC call stream handler

`@GrpcStreamCall()`데코레이터는 grpc.ServerDuplexStream과 같은 함수 매개 변수를 제공하며 `.on('data',callback)`, `.write(message)`또는 `.cancel()`과 같은 표준 메소드를 지원합니다. 사용 가능한 방법에 대한 전체 설명서는 [여기](https://grpc.github.io/grpc/node/grpc-ClientDuplexStream.html)에서 찾을 수 있습니다.

```typescript
// Set decorator with selecting a Service definition from protobuf package
// the string is matching to: package proto_example.orders.OrdersService
@GrpcStreamCall('orders.OrderService')
handleStream(stream: any) {
  stream.on('data', (msg: any) => {
    console.log(msg);
    // Answer here or anywhere else using stream reference
    stream.write({
      shipmentType: {
        carrier: 'test-carrier',
      },
    });
  });
}
```

이 데코레이터에는 특정 리턴 매개 변수를 제공할 필요가 없습니다. 스트림은 다른 표준 스트림 유형과 같은 방식으로 처리될 것으로 예상됩니다.
