본문 바로가기

네트워크

[네트워크/개념] gRPC(remote procedure call)

목차
1. grpc란 무엇인가
2. grpc의 장점
3. rpc의 핵심 목표
4. 예제 코드
5. 마치며

 

 

🤔 grpc란 무엇인가

회사에서 grpc라는 개념을 접하면서 흥미를 가지게 되었다. 그래서 따로 시간을 내서 공부한 내용을 정리해보려한다.

 

gRPC는 Google에서 개발한 고성능, 오픈소스 원격 프로시저 호출(Remote Procedure Call, RPC) 프레임워크입니다. 간단히 말해서, 네트워크를 통해 다른 서버의 함수를 마치 로컬 함수처럼 호출할 수 있게 해주는 기술입니다.

 

 gRPC에 대한 정의는 위와 같다. Remote Procedure Call. 말그대로 서버에 작성된 함수(프로시저)를 클라에서 선언한 함수마냥 쓸수 있게 해주는 기술이다. 물론 실제로 서버의 코드를 클라에서 쓸수 있다는 이야기가 아니다. 작성된 코드의 패턴이 그렇게 보인다는 것일뿐.

 

 gRPC는 구글에서 만든 RPC 시스템이라 gRPC이다. HTTP2 기반으로 동작하며 구글에서 만든 프로토콜인 Protobuf를 이용하여 직렬화한 데이터를 주고 받는 구조라는 것이 큰 특징.

 

보통 백엔드에서는 100이면 100 Json을 쓰게 되는데, Protobuf를 쓰면 .proto 파일을 따로 작성해줘야 한다는 수고스러움이 있긴하지만 성능면에서는 확실히 JSON과 비교 안될정도로 빠르다.

 

 

 

📘 grpc의 장점

앞에서도 언급되었듯이 grpc는 일반적인 백엔드 api를 호출해서 데이터를 주고받는것 보다 성능면에서 우수하다. 물론 JSON 직렬화 방식을 사용하는 보편적인 백엔드 서버가 나쁘다는 의미가 아니다. 접근성이나 범용성면에서는 기존의 백엔드(REST API)가 훨씬 우수하다.

 

gRPC의 경우 직렬화 방식으로 protobuf를 사용하다보니 클라와 서버간 주고받는 패킷이 정확하게 규격화되어 있어 데이터의 일관성이 지켜진다는 특징이 있으며, JSON이 아닌 바이너리 형태로 데이터를 주고받다보니 훨씬 가볍고 빠르다는 장점이 있다. 전체적으로 정리하자면 아래와 같다.

 

🔍 REST API vs gRPC 차이점 요약

통신 프로토콜 HTTP/1.1 HTTP/2
데이터 포맷 JSON Protocol Buffers (protobuf)
성능 느림 (텍스트 기반, 파싱 비용 높음) 빠름 (바이너리, 압축, 스트리밍)
계약 정의 없음 (Swagger 등 별도 사용) .proto로 엄격하게 정의
스트리밍 지원 제한적 클라이언트/서버/양방향 스트리밍 완벽 지원
브라우저에서 사용 O 제한적 (gRPC-Web 필요)
언어 간 통신 좋지만 직렬화 필요 매우 뛰어남 (protobuf로 자동 코드 생성)
에러 처리 HTTP Status Code 위주 gRPC 상태 코드 체계 있음

 

🛰 rpc의 핵심 목표

 

그럼 여기까지 rpc의 장점에 대해서 찬찬히 뜯어보았다. 결국 결론을 내자면 JSON 직렬화 대신 Protobuf를 채용하여 데이터의 일관성을 보장하고 바이너리 방식의 데이터를 전송하여 성능면에서 우수하다. 성능면에서 좋다는건 알겠는데, 결국 rpc라는 기술을 왜 써야하는지는 납득이 잘 가지 않을 수 있다.

 

rpc 기술자체는 성능면에서 우수한것도 있지만 궁극적인 목표는 아래와 같이 정리할 수 있다.

“복잡한 네트워크 통신을 숨기고, 함수 호출처럼 보이게 한다”

  • proto로 계약 정의
  • 자동으로 클라이언트/서버 코드 생성
  • HTTP/2 기반으로 빠름
  • 다양한 언어에서 통신 가능

 

 

💡 예제코드

📁 greeter.proto

 
syntax = "proto3";

option csharp_namespace = "RpcDemo";

package greet;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

 

🖥 서버 (GreeterService.cs)

using Grpc.Core;
using RpcDemo;

public class GreeterService : Greeter.GreeterBase
{
    public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = $"Hello, {request.Name}!"
        });
    }
}

 

🧑‍💻 클라이언트 (Program.cs)

using Grpc.Net.Client;
using RpcDemo;

var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);

Console.Write("Name: ");
var name = Console.ReadLine();

var reply = await client.SayHelloAsync(new HelloRequest { Name = name });

Console.WriteLine("Server said: " + reply.Message);

 

 

클라이언트에 작성된 코드 패턴을 보면 서버에 있는 SayHello 함수를 클라에 선언된 함수처럼 사용하고 return 값을 받고 있는 것을 확인할 수 있다.

 

 

📜 마치며

grpc에 대한 기본적인 내용은 위와 같이 정리할 수 있을것 같다. 이론적인 학습만으론 내것으로 만들 수 없으니 회사 일이랑 별개로 사이드 프로젝트를 하나 해보려한다.

 

grpc를 적용한 게임 서버를 개발해보는 것을 목표로 생각하고있다. 간단하게 유니티 클라를 붙이고 배포 시스템 만들고, 프론트 웹페이지도 하나 만들어서 게임 운영을 위한 어드민 페이지도 간단하게 띄우면 좋지 않을까.. 생각하고 있는데 배보다 배꼽이 더 큰거 같기도 하고.. 하고 싶은건 많은데 요새 퇴근을 매일 늦게 하고 있는 바람에 또 쉽지는 않을거 같다.

 

사이트 플젝을 시작하게 되면 진행사항들을 간단하게 정리할 수 있도록 해야겠다.