Programming/기타

Protobuf 를 통한 FE, BE 간 통신 만들기 - B/E

armyost 2025. 4. 21. 02:39
728x90

Setup

Setting up a new project is quite simple with the Nest CLI. With npm installed, you can create a new Nest project with the following commands in your OS terminal:

$ npm i -g @nestjs/cli
$ nest new nest new protobuf-sample

 

 

Installation

To start building gRPC-based microservices, first install the required packages:

$ npm i --save @grpc/grpc-js @grpc/proto-loader

 

 

 

Protoc 컴파일러 설치

https://www.npmjs.com/package/ts-proto

 

ts-proto

[![npm](https://img.shields.io/npm/v/ts-proto)](https://www.npmjs.com/package/ts-proto) [![build](https://github.com/stephenh/ts-proto/workflows/Build/badge.svg)](https://github.com/stephenh/ts-proto/actions). Latest version: 2.7.0, last published: a month

www.npmjs.com

 

컴파일

protoc --plugin=protoc-gen-ts_proto="C:/Users/jongpo.kim/Desktop/01.WORKSPACE/protobuf-sample/node_modules/.bin/protoc-gen-ts_proto.cmd" --ts_proto_out=./hero/ ./hero/hero.proto

 

 

 

main.ts

import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions } from '@nestjs/microservices';
import { AppModule } from './app.module';
import { grpcClientOptions } from './grpc-client.options';

async function bootstrap() {
  /**
   * This example contains a hybrid application (HTTP + gRPC)
   * You can switch to a microservice with NestFactory.createMicroservice() as follows:
   *
   * const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, {
   *  transport: Transport.GRPC,
   *  options: {
   *    package: 'hero',
   *    protoPath: join(__dirname, './hero/hero.proto'),
   *  }
   * });
   * await app.listen();
   *
   */
  const app = await NestFactory.create(AppModule);
  app.connectMicroservice<MicroserviceOptions>(grpcClientOptions);

  await app.startAllMicroservices();
  await app.listen(3001);
  console.log(`Application is running on: ${await app.getUrl()}`);
}
bootstrap();

 

 

grpc-client.options.ts

import { ReflectionService } from '@grpc/reflection';
import { GrpcOptions, Transport } from '@nestjs/microservices';
import { join } from 'path';

export const grpcClientOptions: GrpcOptions = {
  transport: Transport.GRPC,
  options: {
    package: 'hero', // ['hero', 'hero2']
    protoPath: join(__dirname, './hero/hero.proto'), // ['./hero/hero.proto', './hero/hero2.proto']
    onLoadPackageDefinition: (pkg, server) => {
      new ReflectionService(pkg).addToServer(server);
    },
  },
};

 

 

In the nest-cli.json file, we add the assets property that allows us to distribute non-TypeScript files, and watchAssets - to turn on watching all non-TypeScript assets. In our case, we want .proto files to be automatically copied to the dist folder.

{
  "compilerOptions": {
    "assets": ["**/*.proto"],
    "watchAssets": true
  }
}

 

 

Sample gRPC service

Let's define our sample gRPC service called HeroesService. In the above options object, theprotoPath property sets a path to the .proto definitions file hero.proto. The hero.proto file is structured using protocol buffers. Here's what it looks like:

content_copy

// 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;
}

 

 

 

 

heroes.controller.ts

@Controller()
export class HeroesController {
  @GrpcMethod('HeroesService', 'FindOne')
  findOne(data: HeroById, metadata: Metadata, call: ServerUnaryCall<any, any>): Hero {
    const items = [
      { id: 1, name: 'John' },
      { id: 2, name: 'Doe' },
    ];
    return items.find(({ id }) => id === data.id);
  }
}

 

https://github.com/armyost/protobuf-sample