Nodejs

 

NestJS gRPC 연동하기 - 고성능 서비스 간 통신

 

gRPC는 Google에서 개발한 오픈소스 RPC(Remote Procedure Call) 프레임워크로, HTTP/2 기반의 빠르고 효율적인 직렬화 방식(Protocol Buffers, Protobuf)을 사용합니다.

 

 

1. gRPC란?

  • Protocol Buffers 기반 직렬화: JSON보다 가볍고 빠른 직렬화 포맷.

  • HTTP/2 기반: 멀티플렉싱, 스트리밍 지원.

  • 양방향 스트리밍: 서버와 클라이언트가 실시간으로 메시지를 주고받을 수 있음.

  • 강력한 타입 안전성: 서비스 계약이 .proto 파일로 정의되므로 클라이언트-서버 간 인터페이스가 명확.

 

2. 라이브러리 설치

NestJS에서 gRPC를 사용하려면 관련 패키지를 설치해야 합니다.

pnpm i @nestjs/microservices @grpc/grpc-js @grpc/proto-loader

 

 

3. Docker 환경

gRPC 자체는 별도의 브로커(예: Redis, RabbitMQ)가 필요 없고, 서비스 간 직접 통신을 지원합니다. 따라서 docker-compose.yml에는 별도 설정이 필요하지 않습니다. 다만 서비스들이 서로를 네트워크 이름으로 인식할 수 있어야 합니다.

예: user 서비스가 gRPC 서버라면 product 서비스에서 user:50051로 접근 가능.

 

 

4. gRPC 프로토콜 정의 (.proto 파일)

서비스 간 통신 규약은 .proto 파일로 정의합니다.

syntax = "proto3";

package user;

service UserService {
  rpc FindOne (FindOneRequest) returns (FindOneResponse);
}

message FindOneRequest {
  string id = 1;
}

message FindOneResponse {
  string id = 1;
  string name = 2;
  string email = 3;
}
  • service UserService: gRPC 서비스 정의.

  • FindOne: 원격에서 호출할 수 있는 메서드.

  • FindOneRequest / FindOneResponse: 요청과 응답 메시지 타입.

 

✅ 스트리밍 방식 예시

단순 요청/응답뿐 아니라 스트리밍 방식도 함께 다뤘습니다. 아래는 예제 코드입니다:

syntax = "proto3";

package codefactory;

service UserService {
  rpc Unary(UserRequest) returns (UserResponse);
  rpc ClientSideStreaming(stream UserRequest) returns (UserResponse);
  rpc ServerSideStreaming(UserRequest) returns (stream UserResponse);
  rpc BiDirectionalStreaming(stream UserRequest) returns (stream UserResponse);
}

message UserRequest {
  string name = 1;
}

message UserResponse {
  string result = 1;
}
  • Unary: 일반적인 요청-응답 패턴.

  • ClientSideStreaming: 클라이언트가 여러 요청을 스트리밍으로 보내고 서버가 단일 응답 반환.

  • ServerSideStreaming: 서버가 여러 응답을 스트리밍으로 반환.

  • BiDirectionalStreaming: 클라이언트와 서버가 양방향으로 스트리밍.

 

 

5. NestJS gRPC 서버 설정

main.ts에서 gRPC 서버를 설정합니다.

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { join } from 'path';

async function bootstrap() {
  const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, {
    transport: Transport.GRPC,
    options: {
      package: 'user',
      protoPath: join(__dirname, './proto/user.proto'),
      url: '0.0.0.0:50051',
    },
  });

  await app.listen();
}
bootstrap();
  • transport: Transport.GRPC → gRPC 서버로 동작.

  • protoPath → gRPC 프로토콜 정의 파일 경로.

  • url: '0.0.0.0:50051' → 서비스가 50051 포트에서 대기.

 

 

 

6. gRPC 클라이언트 설정

AppModule에서 gRPC 클라이언트를 등록합니다.

ClientsModule.register([
  {
    name: 'USER_SERVICE',
    transport: Transport.GRPC,
    options: {
      package: 'user',
      protoPath: join(__dirname, './proto/user.proto'),
      url: 'user:50051', // docker-compose 내 user 서비스 접근
    },
  },
]);

 

 

 

7. gRPC 서비스 구현 예시

import { Controller } from '@nestjs/common';
import { GrpcMethod } from '@nestjs/microservices';

@Controller()
export class UserController {
  @GrpcMethod('UserService', 'FindOne')
  findOne(data: { id: string }) {
    return { id: data.id, name: '홍길동', email: 'hong@test.com' };
  }
}
  • @GrpcMethod('UserService', 'FindOne') → .proto에 정의된 서비스와 메서드에 매핑.

  • 클라이언트에서 FindOne을 호출하면 해당 메서드가 실행됨.

 

 

 

8. gRPC 장단점

✅ 장점:

  • 고성능, 저지연.

  • 강력한 타입 보장.

  • 양방향 스트리밍 지원.

⚠️ 단점:

  • 러닝 커브 (proto 파일 정의 필요).

  • 브라우저 직접 호출이 어려워 gRPC-Web 같은 별도 게이트웨이 필요.

 

 

9. 마무리

이번 정리에서는 NestJS에서 gRPC를 활용해 서비스 간 통신을 구현하는 방법을 살펴봤습니다. Redis나 RabbitMQ처럼 메시지 브로커를 거치지 않고 직접 통신하기 때문에 지연을 최소화할 수

있습니다.

 

대신 서비스 간 결합도가 높아질 수 있으므로, 시스템 설계 시 트레이드오프를 고려해야 합니다.

 

특히 스트리밍 방식(Unary, Client-Side, Server-Side, Bi-Directional)을 지원하므로 실시간 데이터 전송이 필요한 환경에서 강력한 선택지가 될 수 있습니다.

 

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

둘이 먹다가 하나가 죽어도 모르겠다 , 음식 맛이 매우 좋다는 말.

댓글 ( 0)

댓글 남기기

작성