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)을 지원하므로 실시간 데이터 전송이 필요한 환경에서 강력한 선택지가 될 수 있습니다.













댓글 ( 0)
댓글 남기기