샘플 코드가 있다.
// hero/hero.proto
syntax = "proto3";
package hero;
service HeroesService {
rpc FindOne (HeroById) returns (Hero) {}
}
message HeroById {
int32 id = 1;
}
message Hero {
int32 id = 1;
string name = 2;
}
위 hero.proto
화일을 https://www.npmjs.com/package/ts-proto 이용해 컴파일하면
(protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=. ./hero.proto
),
interface
, decorator
등을 포함한 hero.ts
화일이 생긴다.
/* eslint-disable */
import { GrpcMethod, GrpcStreamMethod } from "@nestjs/microservices";
import { Observable } from "rxjs";
export const protobufPackage = "hero";
export interface HeroById {
id: number;
}
export interface Hero {
id: number;
name: string;
}
export const HERO_PACKAGE_NAME = "hero";
export interface HeroesServiceClient {
findOne(request: HeroById): Observable<Hero>;
findMany(request: Observable<HeroById>): Observable<Hero>;
}
export interface HeroesServiceController {
findOne(request: HeroById): Promise<Hero> | Observable<Hero> | Hero;
findMany(request: Observable<HeroById>): Observable<Hero>;
}
export function HeroesServiceControllerMethods() {
return function (constructor: Function) {
const grpcMethods: string[] = ["findOne"];
for (const method of grpcMethods) {
const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
GrpcMethod("HeroesService", method)(constructor.prototype[method], method, descriptor);
}
const grpcStreamMethods: string[] = ["findMany"];
for (const method of grpcStreamMethods) {
const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
GrpcStreamMethod("HeroesService", method)(constructor.prototype[method], method, descriptor);
}
};
}
export const HEROES_SERVICE_NAME = "HeroesService";
여기까지는 client, server 공통사항이고,
https://levelup.gitconnected.com/step-by-step-guide-grpc-microservices-in-nestjs-554b498d3f7
https://github.com/nestjs/nest/blob/master/sample/04-grpc/src/hero/hero.controller.ts 만큼 복작하지 않게,
hero.ts
를 이용해 아래와 같이 간단하게 작성할 수 있다.
import { Controller, UseInterceptors } from '@nestjs/common';
import { GrpcLoggingInterceptor } from '@packages/lib';
import { Observable } from 'rxjs';
import { Hero, HeroById, HeroesServiceController, HEROES_SERVICE_NAME } from './hero';
@UseInterceptors(GrpcLoggingInterceptor)
@Controller()
export class HeroController implements HeroesServiceController {
@GrpcMethod(HEROES_SERVICE_NAME, 'findOne')
findOne(request: HeroById): Promise<Hero> | Observable<Hero> | Hero {
const items = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Doe' }
];
return items.find(({ id }) => id === request.id);
}
}
https://docs.nestjs.com/microservices/grpc#client 비슷하지만,
hero.ts
를 이용해 아래와 같이 작성할 수 있다.
import { ClientGrpc } from '@nestjs/microservices';
import { Inject, Injectable } from '@nestjs/common';
import { HEROES_SERVICE_NAME, HeroesServiceClient } from './hero';
@Injectable()
export class CommonGrpcService {
private heroesService: HeroesServiceClient;
constructor(@Inject('HERO_PACKAGE') private client: ClientGrpc) {}
onModuleInit() {
this.heroesService = this.client.getService<HeroesServiceClient>(HEROES_SERVICE_NAME);
}
getHero() {
return this.heroesService.findOne({ id: 1 });
}
}
client, server 둘 다 gRPC code generation(dynamic, static)과 관계 없이
https://github.com/nestjs/nest/tree/master/sample/04-grpc/src/hero/interfaces 와
https://github.com/nestjs/nest/blob/master/sample/04-grpc/src/hero/hero.controller.ts#L12-L15
export interface HeroById {
id: number;
}
export interface Hero {
id: number;
name: string;
}
interface HeroesService {
findOne(data: HeroById): Observable<Hero>;
findMany(upstream: Observable<HeroById>): Observable<Hero>;
}
타입을 선언해야 한다.
그런데, https://www.npmjs.com/package/ts-proto 이용해 컴파일하면,
server 도 간단하게 구현할 수 있고, client, server에 필요한 type 도 생성된다.
참고)