gRPC

유기훈·2025년 4월 4일

인프런 "파이썬으로 쉽게 배우는 gRPC!" 강의 내용 정리

gRPC

gRPC란?

  • google에서 개발한 RPC
  • 네트워크를 통해 원격 시스템의 함수를 내 함수처럼 쓰는 기술

gRPC 기본 아키텍쳐

  • Proto라는 부분은 gRPC에서 사용할 데이터와 제공되는 서비스를 정의하는 부분
  • Protocol Buffers라는 언어로 작성하는데 메시지 직렬화 방식이다.
  • 이컬 통해 실제로 전송되는 데이터나 제공되는 서비스 언어의 코드로 자동 생성되어 이 자동 생성된 코드 속에는 메시지 직렬화, 역직렬화, 서비스 인터페이스 등 다양한 코드를 포함한다.

HTTP 2.0

  • gRPC는 HTTP 2.0 사용
  • gRPC는 멀티플렉싱 기능을 지원한다. 멀티플렉싱은 여러 개의 요청과 응답을 하나의 TCP 연결로 처리하는 방식을 말한다.
    - TCP 연결 수립은 꽤나 복잡하고 어려운 작업. HTTP2는 여러 개의 요청을 하나의 TCP 연결로 처리함으로써 지연 시간을 확 줄인다.
  • HTTP 2.0은 압축 알고리즘을 사용헤서 헤더 크기 자체를 줄인다.
  • 서버 푸시 기능을 지원한다. 서버 푸시란 서버가 클라이언트의 요청 없이도 필요한 데이터를 미리 전송하는 기능
  • 1.1 버전은 텍스트 기반 프로토콜인데, 2.0은 컴퓨터에 최적화된 바이너리 프레임을 사용하기 때문에 데이터 처리 속도를 향상시킨다.

프로토 버퍼

  • 프로토콜 버퍼는 강력한 타입 시스템과 효율적인 데이터 직렬화를 자랑하는 메커니즘이다. 프로토버퍼는 타입 시스템이 굉장히 강력하다. 데이터의 구조와 타입, 그리고 제공되는 서비스를 명확하게 정의함으로써 서비스의 인터페이스와 서비스 간의 인터페이스를 명확하게 한다.
  • Protocol Buffers로 한번 데이터를 정의하고 나면, 특정 개발 언어에 맞는 코드로 자동 컴파일 할 수 있다.

통신적인 측면

  • gRPC는 양방향 스트리밍 지원한다.
  • 양방향 스트리밍은 서버와 클라이언트가 데이터를 스트림 형태로 편하게 주고받을 수 있다.

gRPC 단점

  • 브라우저의 지원이 제한된다.
  • gRPC 웹이라는 새로운 프레임워크가 존재하긴 함.
  • 디버깅이 어렵다. 성능을 위해서 바이너리 형식으로 다루다보니 응답과 요청이 직관적이지 못하다.
  • 학습 곡선이 있기는 있다.

gRPC의 모델

통신 모델

  • gRPC는 기본적으로 서버 클라이언트 모델로 동작한다.
  • gRPC에서는 세가지 구성요소가 존재한다.
  1. 서비스
  • 서비스는 서버가 클라이언트에게 제공하는 기능 또는 작업을 의미한다.
  1. 메시지
  • 클라이언트가 서버에게 요청하거나 서버가 클라이언트에게 응답할 때 데이터를 담는 일종의 컨테이너
  1. RPC
  • RPC는 클라이언트가 서버의 메서드를 호출하는 방식을 말한다.
  • 원격 프로시저 호출은 기존의 함수 호출과 매우 유사하게 느껴진다. 클라이언트는 마치 로컬에서 메서드를 호출하듯이 서버의 메서드를 호출할 수 있다.

통신 구성요소

  1. 채널
  • gRPC에서 서버와의 연결 통로를 의미한다.
  • 클라이언트가 서버에 접속해서 메서드를 호출하고 데이터를 주고받기 위해서는 채널을 통해야 한다.
  • 채널은 기본적으로 서버의 IP 주소와 포트 번호를 사용해서 생성할 수 있다.
  • 채널을 생성할 때는 보안 채널, 비보안 채널 등 다양한 옵션을 줄수 있다.
  • 이러한 채널은 스텁을 만들 때 필요하다.
  1. 스텁
  • 스텁은 클라이언트 대신 서버랑 대화해주는 놈
  • 서버와 연결 통로를 만들었는데 그 밖에도 서버를 관리해줄 부분이 많은데 서버랑 통신하는 복잡한 부분은 스텁이 알아서 처리해준다.
  • 스텁은 프로토 파일의 서비스 인터페이스를 정의하면 컴파일 시 자동으로 생성된다.
  1. 프로토 버퍼
  • gRPC의 메시지를 정의하고 gRPC의 서비스를 정의하는 인터페이스 정의 언어
  • 데이터를 압축할 수 있고, 주고받을 때 사용할 수도 있는 다목적 포맷
  • 프로토파일이라는 파일 속에 프로토콜 버퍼 문법을 사용해서 메시지와 서비스를 정의할 수 있다.

채널

  • 프로토콜 버퍼와는 직접적인 연관은 없지만 이 채널은 프로토콜 버퍼가 만들어내는 스텁과 관련이 있다.
  • 스텁을 만들 때 채널을 통해 만들 수 있는데 이 채널을 전달만 해주면 복잡한 통신과 관련된 부분은 모두 스텁이 알아서 치리해준다.

Protocol Buffers

프로토콜 버퍼란

  • 데이터 직렬화 매커니즘
  • 메시지와 서비스를 정의하고 이걸 컴파일해서 특정 언어에 맞는 서버와 클라이언트 코드를 자동으로 생성할 수 있다.
  • 하나의 프로토 파일로 다양한 클라이언트 서버 코드가 자동 생성되기 때문에 타입 불일치로 인한 에러 가능성이 확 줄어들게 된다.
  • 또한 바이너리 형식으로 데이터를 다루기 때문에 빠르고 효율적인 통신이 가능하게 한다.
  • 데이터 타입을 자동으로 생성해주다 보니 다른 언어 간에 통신할 때도 데이터 불일치로 인한 에러 가능성이 거의 없다.

프로토 버퍼 기본 구조

  • 가장 위에는 문법적으로 어떤 문법을 사용할지 정의한다.
  • syntax = "proto3"
  • 패키지 이름을 정의하는 부분: 패키지 이름은 이름 공간을 분리해준다. 메시지를 정의할 때는 필드나 메시지 이름이 겹치는 경우가 상당히 많다. 패키지 이름을 정의하면 이름 공간을 분리하게 되면 이름 충돌 가능성이 줄어든다.
  • import는 다른 프로토 파일에서 정의한 메시지를 사용할 필요가 있을 때 사용한다.

메시지

  • 메시지를 정의하는 방법은 message 키워드를 사용해서 할 수 있다.
  • 하나의 메시지는 다양한 필드를 가질 수 있는데 필드는 타입, 이름, 식별자 순으로 정의되어 있다.
  • 타입은 해당 데이터의 타입
    식별자
  • string name = 1; 이라고 되어 있으면 name이라는 필드에 1이 들어가는게 아니라 name이라는 필드의 정의 순서는 1번이라는 식별자를 부여한 것.
  • 식별자는 다른 필드와 겹쳐서는 안된다.

데이터 타입

기본 데이터 타입

  • 프로토버퍼의 타입과 각 언어의 타입을 찾아보면된다.
    배열
  • 기본 데이터 타입 앞에 repeated 키워드를 붙이면 배열이 된다.
repeated string hobbies = 4;

열거형

  • 아래와 같이 정의하면 된다.
  • 옆에 있는 숫자는 식별자다.
enum PhoneType {
  MOBILE = 0;
  HOME = 1;
  WORK = 2;
}

중첩 메시지

  • 타입을 구조체나 객체같이 사용 가능
message PhoneNumber {
  string number = 1;
  PhoneType type = 2;
}

message Person {
  repeated PhoneNumber phones = 0;
}

옵션

  • 서비스나 데이터에 추가적인 정보를 제공하는 방법
  • 옵션은 괄호 ([])안에 지정되며, 다음의 형식을 갖는다.
    deprecated
  • 특정 필드를 더 이상 사용하지 않는다고 생각해보자. 이걸 프로토파일을 수정해서 새로 컴파일을 진행하면 기존 코드들은 호환성이 유지되지 않기 때문에 새로 구현을 진행해야 한다. 근데 이걸 막기 위해 deprecated 옵션을 사용한다.
    packed
  • 반복되는 필드의 인코딩을 최적화한다.
    default
  • 필드의 기본값을 설정한다.

필드 예약하기

  • 나중에 사용할 필드를 미리 예약할 수 있다.
  • 호환성 유지에도 사용된다. (가장 큰 이유)
message MyMessage {
  reserved 2, 15, 9 to 11; // 필드 번호 2, 15, 9부터 11까지 예약
  reserved "foo", "bar"; // 필드 이름 예약

  • 키-값 쌍을 저장하는 데 사용되는 데이터 타입
message MyMessage {
  map<string, int32> scores = 1; // 문자열 key와 값 int32를 가지는 맵

gRPC 서비스 정의

  • .proto 파일에서 서비스 및 RPC 메서드를 정의한다.
service Greeter {
  rpc SayHello (HelloRequest) returns (HelloRepy) {}
}
  • service: 서비스 이름을 정의한다.
  • rpc: RPC 메서드를 정의한다. (메서드 이름 요청 메시지 유형, 응답 메시지 유형)

컴파일

  • .proto 파일에서 서비스 및 RPC 메서드를 정의한다.
  • 각 언어에 맞는 컴파일 방법을 통해 컴파일한다.

gRPC 통신 패턴

스트리밍이란

  • 클라이언트와 서버 간에 연속적인 데이터 흐름을 주고받는 방식
  • 네 가지 스트리밍 방법을 지원
  • gRPC의 스트리밍은 실시간 데이터 전송, 대용량 데이터 처리, 비동기 통신 등에 유용하다.

Unary RPC

가장 기본적인 통신 방식

  • 클라이언트가 서버에 요청을 보내고 서버가 이에 대한 응답을 한 번 반환!
  • HTTP의 Request-Response 모델과 매우 유사!

장점

  • 간단하고 직관적이다.
  • 오버헤드가 적다.
  • 효율적이다.

단점

  • 제한된 데이터 전송
  • RPC의 장점을 살리지 못하는 통신 방식

동작 방식

  • 클라이언트가 요청한다. -> 서버가 처리한다. -> 서버가 응답한다. -> 클라이언트가 응답을 수신한다.

활용 사례!

  • 데이터 베이스 조회
  • 계산 요청
  • 상태 확인

Server-Client, Client-Server streaming

Server streaming과 Client Streaming

  • 한 쪽에서 계속해서 데이터를 보내고 다른 한 쪽은 하나의 데이터만 보내는 방식
  • 여러 개의 요청과 하나의 응답
  • 하나의 요청과 여러 개의 응답

장점

  • 많은 데이터를 효과적으로 전송 가능!
  • 실시간 데이터 전송이 가능!

단점

  • 응답을 모두 받을 때 까지 대기해야한다.

Bidirectional Streaming RPC

클라이언트와 서버가 서로 스트림 형태로 데이터를 주고받는 방식

  • 가장 gRPC의 장점을 잘 활용하는 스트리밍 방식

장점

  • 실시간 데이터 전송이 가능!
  • 대화형 애플리케이션
  • 상호 작용

단점

  • 구현이 다른 통신 방식에 비해 복잡하다.

동작 방식

  • 클라이언트 요청 스트리밍
  • 서버 수신 및 처리
  • 서버 응답 스트리밍
  • 클라이언트 수신 및 처리

활용 사례

  • 채팅
  • 온라인 게임
  • 실시간 도구

gRPC 파이썬/자바 용어 정리

역할Python 용어Java 용어설명
서버와의 연결grpc.insecure_channel()ManagedChannelBuilder.forAddress()gRPC 서버에 연결하는 채널 객체
클라이언트 스텁Stub, FutureStub, AsyncStubHelloServiceGrpc.HelloServiceBlockingStub클라이언트에서 서버 메서드를 호출하는 객체
서버 등록add_XXXServicer_to_server()extends HelloServiceGrpc.HelloServiceImplBase서버 구현을 gRPC에 등록
메시지 객체HelloRequest()HelloRequest.newBuilder()요청/응답 메시지 클래스
서버grpc.server()GrpcServerApplication@Service 구현체gRPC 서버 인스턴스
응답 보내기context.set_code(), context.set_details()responseObserver.onNext(), onCompleted()응답 반환 방식
코드 생성 도구grpc_tools.protocprotobuf-maven-pluginprotoc.proto 파일을 소스 코드로 변환하는 도구
요청 방식stub.SayHello()blockingStub.sayHello()gRPC 호출 방식

gRPC 통신 패턴 마다의 차이 정리

Unary RPC

.proto service 메서드 정의 방법

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

Server Streaming RPC

.proto service 메서드 정의 방법

service UserService {
  rpc GetUserList (UserFilter) returns (stream User);
}

Client Streaming RPC

.proto service 메서드 정의 방법

service FileService {
  rpc UploadFile (stream FileChunk) returns (UploadStatus);
}

Bidirectional Streaming RPC

.proto service 메서드 정의 방법

service ChatService {
  rpc Chat (stream ChatMessage) returns (stream ChatMessage);
}
profile
개발 블로그

0개의 댓글