[NestJS]- gRPC Proto(feat.REST API)

Dragon_Tack·2025년 2월 16일
post-thumbnail

gPRC 에대해서 알아보자. gRPC는 MSA 환경에서 서비스 간 통신을 위한 효율적인 방법으로 주목받고 있고, NestJS Docs에 간략하게 설명되어았어 평소에 관심이 있어 글을 써보고자 한다. 모듈화된 아키텍처와 다양한 기능을 제공하여 개발 생산성을 높여준다. 특히 마이크로서비스 아키텍처 (MSA) 환경에서 NestJS는 강력한 성능과 확장성을 제공하며, gRPC는 MSA 환경에서 서비스 간 통신을 위한 효율적인 방법으로 주목받고 있고, 간단한 기능을 만들어 보고자 한다.

gRPC란 무엇인가?

gRPC (Google Remote Procedure Call)는 Google에서 개발한 고성능의 오픈소스 RPC (Remote Procedure Call) 프레임워크입니다. Protocol Buffers를 사용하여 데이터를 직렬화하고 HTTP/2를 기반으로 통신하여 높은 성능과 효율성을 제공합니다.

NestJS에서 gRPC를 사용하는 이유

1. 높은 성능과 효율성

gRPC는 Protocol Buffers를 사용하여 데이터를 직렬화하므로 JSON과 같은 텍스트 기반 형식에 비해 훨씬 빠르고 효율적인 통신이 가능합니다. 특히 대규모 트래픽 처리나 실시간 통신이 필요한 환경에서 gRPC의 성능은 빛을 발합니다.

2. 엄격한 계약 기반 통신

gRPC는 Protocol Buffers를 사용하여 서비스 인터페이스를 정의하고, 이를 기반으로 코드를 자동 생성하여 클라이언트와 서버 간의 계약을 명확하게 합니다. 이는 개발 과정에서 오류를 줄이고, 서비스 간 호환성을 유지하는 데 도움을 줍니다.

3. 다양한 언어 지원

gRPC는 다양한 프로그래밍 언어를 지원하여 MSA 환경에서 여러 서비스가 각기 다른 언어로 개발되었더라도 원활하게 통신할 수 있도록 합니다. NestJS는 gRPC 클라이언트 및 서버를 쉽게 구현할 수 있도록 기능을 제공합니다.

4. 양방향 스트리밍

gRPC는 양방향 스트리밍을 지원하여 클라이언트와 서버가 동시에 데이터를 주고받을 수 있습니다. 이는 실시간 채팅, 게임 등 양방향 통신이 필요한 애플리케이션 개발에 유용합니다.

5. 마이크로서비스 아키텍처에 최적화

gRPC는 MSA 환경에서 서비스 간 통신을 위한 효율적인 방법을 제공합니다. 각 서비스는 gRPC 인터페이스를 통해 다른 서비스와 통신하며, 이는 MSA의 핵심 가치인 독립적인 배포 및 확장을 가능하게 합니다.

NestJS에서 gRPC 활용하기

NestJS는 @nestjs/microservices 모듈을 통해 gRPC를 쉽게 통합할 수 있습니다. gRPC 서버를 구현하고, 클라이언트에서 gRPC 서비스를 호출하는 과정을 간단하게 처리할 수 있습니다. 또한 NestJS의 모듈 시스템과 DI (Dependency Injection)을 활용하여 gRPC 관련 코드를 구조화하고 관리하기 용이합니다.

실습

Proto 예제


// hero/hero.proto
syntax = "proto3";

package hero;

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

message HeroById {
  int32 id = 1;
}

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

간혹가다가 nest/common, nest/core 버전이 상이해 microservices모듈이 설치가 안될때가 있는데, 이부분은 버전확인후 최신화 업데이트를 진행을 선행하고 시작해줘야한다...! (삽질해봐서 미리공유드립니다)

npm outdated

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

폴더 구조는 아래와 같이 진행한다.

nestjs-grpc-microservice/
│── apps/
│   │── main-service/          # Main API Gateway (REST + gRPC Client)
│   │   │── src/
│   │   │   │── main.ts        # Main entry point
│   │   │   │── app.module.ts  # App module
│   │   │   └── hero/
│   │   │       │── hero.controller.ts  # REST API Controller (calls gRPC client)
│   │   │       └── hero.service.ts     # Calls gRPC microservice
│   │   └── package.json
│   │
│   └── hero-service/          # gRPC Microservice
│       │── src/
│       │   │── main.ts        # gRPC Server entry point
│       │   │── app.module.ts  # App module
│       │   └── hero/
│       │       │── hero.service.ts     # Implements gRPC service
│       │       └── hero.controller.ts  # gRPC Controller
│       └── package.json
│
│── proto/
│   └── hero.proto              # gRPC Protocol Definition
│
│── package.json
│── tsconfig.json

좌 - gRPC / 우 - REST API + gRPC Client

사전에 정의 된 gRPC와 RESTAPI 와 연동시켜 보다 빠른 응답값으로 서비스를 실습 해봤습니다.

결론

기존 서비스에서 REST API를 통한 Internal Call을 요청하고 응답을 받는 과정에서 응답 지연이 자주 발생했던 문제를 자주 마주했었는데, 이 과정에서 gRPC의 장점이 확실히 드러나긴 했습니다.

장점

성능: gRPC는 레이턴시(Latency) 측면에서 확실히 뛰어납니다. 작은 데이터 패킷과 이진 포맷(Protocol Buffers)을 사용하므로, 빠르고 효율적인 통신이 가능합니다.

단점

브라우저 지원 부족: gRPC는 웹 브라우저에서 직접적으로 지원되지 않아서, gRPC-Web과 같은 별도의 해결책이 필요합니다. 이를 고려해야 할 필요가 있습니다.

성능 측면에서는 gRPC가 매우 뛰어난 선택이지만, 브라우저와의 호환성 문제와 같은 사이드 이슈도 신경 써야 합니다.
그리고, 요구사항에 쫓겨 급하게 결정을 내리던 나 자신에게 다시 한번 반성하는 시간이 되었다는 점도 중요한 깨달음! 😅
간단히 말해서, 성능은 gRPC가 뛰어나지만, 브라우저 환경이나 호환성 측면에서 추가 고려가 필요하고, 항상 적절한 균형을 맞추는 게 중요하다는 이야기

참고문헌 -
https://www.npmjs.com/package/@nestjs/microservices
https://docs.nestjs.com/microservices/grpc#grpc
https://www.youtube.com/watch?v=UkWcjVWs2UQ

profile
고민의 흔적을 늘여놓는 공간

0개의 댓글