[번역] gRPC 핵심 개념

Jake Seo·2021년 1월 22일
1

네트워크

목록 보기
8/16

[번역] gRPC 핵심 개념

Prologue

이 글은 gRPC 공식문서에 있는 글을 번역한 글입니다.

개요

서비스 정의

많은 RPC 시스템과 같이, gRPC는 파라미터와 리턴 타입과 함께 원격에서 호출될 수 있는 메소드들을 명시하는 서비스를 정의하는 아이디어를 근간으로 합니다.

service HelloSerivce {
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  string reply = 1;
}

서비스 메소드

gRPC는 우리가 4가지 종류의 서비스 메소드를 정의할 수 있게 도와줍니다.

Unary RPC

Unary RPC는 단항을 의미합니다. 일반 함수 호출처럼 클라이언트가 하나의 요청을 서버로 보내고 하나의 응답을 받는 것입니다.

rpc SayHello(HelloRequest) returns (HelloResponse);

Server Streaming RPC

Server streaming RPC는 클라이언트가 하나의 요청을 서버로 보내고, 메세지들의 시퀀스를 읽을 수 있는 Stream을 반환받는 것입니다. 클라이언트는 메세지가 더이상 존재하지 않을 때까지, 반환된 스트림을 읽습니다. gRPC는 각 RPC 호출 내부에서 메시지의 순서를 보장합니다.

더이상 존재하지 않을 때까지 읽지 않는다면 서버쪽에서 에러가 송출됩니다.

rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);

Client Streaming RPC

Client Streaming RPC는 제공된 Stream을 이용하여 클라이언트가 메시지의 시퀀스를 작성하고 서버로 보냅니다. 일단 클라이언트가 메시지를 작성하는 것이 끝나면, 서버가 메세지를 읽을 때까지 기다리고 응답을 반환합니다. 마찬가지로 gRPC는 각 RPC 호출 내부에서 메시지 순서를 보장합니다.

rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);

Bidirectional Streaming RPC

Bidirectional Streaming RPC는 서버와 클라이언트 모두 메시지의 시퀀스를 보냅니다. 읽기와 쓰기 모두 Stream을 사용합니다. 두개의 Stream은 독립적으로 운용됩니다. 그래서 클라이언트와 서버는 그것들이 어떤 순서를 가지고 있든지, 읽거나 쓸 수 있습니다. 이를테면, 서버는 응답을 작성하기 전까지 모든 클라이언트 메세지를 받기 위해 기다릴 수 있고 또는 메세지를 작성하거나 읽기 쓰기를 하다가 메세지를 읽을 수도 있습니다. 각 Stream에서 메세지의 순서는 미리 예약되어 있습니다.

rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);

RPC의 다른 타입들에 대해서 알고 싶다면, 아래에 RPC 라이프사이클 섹션이 있습니다.

API 사용하기

.proto 파일 내부의 서비스 정의로부터 시작합니다. gRPC는 클라이언트와 서버사이드 코드를 생성하는 프로토콜 버퍼 컴파일러 플러그인들을 제공합니다. gRPC 사용자들은 일반적으로 이러한 클라이언트 위의 API들을 호출하고, 서버사이드에서 응답하는 API를 구현합니다.

  • 서버 사이드에서는, 서버가 서비스에 의해 정의된 메소드들을 구현하고, 클라이언트 호출을 다루기 위해 gRPC 서버를 운용합니다. gRPC 인프라스트럭쳐는 들어오는 요청들을 디코드하고, 서비스 메소드를 실행하고, 서비스 응답을 인코드합니다.
  • 클라이언트 사이드에서는, 클라이언트가 서비스와 같은 메소드를 구현하는 stub이라고 불리는 (몇몇 언어에서는 clinet라는 용어가 선호되기도 합니다.) 로컬 오브젝트를 갖습니다. 클라이언트는 적절한 프로토콜 버퍼 메세지 타입에서 호출을 위한 파라미터들을 감싸는 로컬 오브젝트 위에 있는 이러한 메소드를 호출할 수 있습니다. gRPC는 서버로 보내는 요청들을 관리하고 서버의 프로토콜 버퍼 응답을 반환합니다.

동기 vs 비동기

응답이 올 때까지 블록되는 동기 RPC 호출은 RPC가 하려고 하는 프로시져 호출의 추상적인 개념과 가장 근사합니다. 하지만 다르게 생각해보면, 네트워크는 본질적으로 비동기적이고 많은 시나리오에서 현재 스레드를 블록킹하는 행위 없이 RPC를 시작할 수 있다는 것은 매우 유용하게 작용합니다.

대부분의 언어에서 gRPC 프로그래밍 API는 동기와 비동기 모두를 입맛에 맞게 제공합니다. 각 언어의 튜토리얼들을 보면 더 많은 정보를 찾아볼 수 있습니다.

RPC 라이프 사이클

이 섹션에서, gRPC 클라이언트가 gRPC 서버의 메소드를 호출했을 때 어떤 일이 일어나는지에 대해 더 자세히 알아봅니다. 완전한 구현 디테일에 대해서는 language-specific 페이지들을 참고하세요.

Unary RPC (단항 RPC)

클라이언트가 단일 요청을 보내고 단일 응답을 받는 가장 간단한 형태의 RPC로 여겨지는 RPC입니다.

  1. 먼저, 클라이언트가 stub 메소드를 호출하면, 서버는 클라이언트가 이 호출과 메소드 이름과 데드라인이 명시되어 있다면 명시된 데드라인에 대한 메타데이터와 함께 RPC를 호출하였다는 것을 알게 됩니다.
  2. 서버는 응답 전에 반드시 보내져야 하는 어떤 초기 메타데이터를 바로 반환해주거나 클라이언트의 요청 메세지를 기다릴 수 있습니다. 어플리케이션의 세부 내용에 따라 이 행동은 달라집니다.
  3. 일단 서버가 클라이언트의 요청 메세지를 갖게 되면, 응답을 만들고 붙이기 위해 필요한 어떤 일이든 합니다. 응답은 이후 상태 세부정보(상태 코드와 선택적 상태 메세지)와 선택적인 추적 기록 메타데이터와 함께 클라이언트에 반환됩니다.
  4. 만일, 응답 상태가 OK라면, 클라이언트는 클라이언트 사이드의 호출을 끝마치는 응답을 받게 됩니다.

Server Streaming RPC

Server Streaming RPC는 단항 RPC와 비슷한데, 클라이언트의 요청에 메세지의 Stream을 반환한다는 것을 제외하고는 비슷합니다. 모든 메세지를 보낸 이후에, 서버의 상태 디테일(상태 코드와 선택적 상태 메세지)와 선택적인 추적 메타데이터 정보가 클라이언트로 보내집니다. 이러한 작업은 서버사이드에서 완료됩니다. 클라이언트는 모든 서버의 메세지들을 가지면, 완료됩니다.

Client Streaming RPC

Client Streaming RPC역시 단항 RPC와 비슷한데, 클라이언트가 단항 메세지 대신 메세지의 Stream을 서버로 보낸다는 점만 빼면 비슷합니다. (일반적으로는 그렇지만 꼭 그렇진 않을 수 있지만) 클라이언트의 모든 메세지를 받은 이후에 서버는 단일 메세지로 응답합니다. (상태 디테일과 선택적 추적 메타 데이터정보도 함께 갑니다.)

Bidirectional Streaming RPC

Bidirectional Streaming RPC에서는, 호출이 메소드를 호출하는 클라이언트와 클라이언트 메타데이터, 메소드 이름, 데드라인을 받는 서버에 의해 초기화 됩니다. 서버는 초기 메타데이터를 다시 돌려보낼지 혹은 클라이언트가 스트리밍 메세지들을 시작하는 것을 기다릴지에 대한 선택이 가능합니다.

클라이언트와 서버사이드 스트림 프로세싱은 어플리케이션에 명시됩니다. 양쪽의 스트림은 독립적이기 때문에, 클라이언트와 서버는 어떤 순서로든 메세지를 읽거나 쓸 수 있습니다. 예를 들면, 메세지를 작성하기 전에 서버는 모든 클라이언트의 메세지를 수신할 때까지 기다릴 수도 있고, 서버와 클라이언트가 핑퐁을 할 수도 있습니다. 핑퐁을 한다는 것은 서버가 요청을 받고 응답을 내보내고 클라이언트가 받았던 응답을 기반으로 또 요청을 보내고 그것을 반복하는 것입니다.

Deadlines/Timeouts

gRPC는 RPC가 DEADLINE_EXCEEDED 에러를 내보내며 종료되기 이전에 클라이언트가 얼마나 오랜시간동안 RPG가 완료될 때까지 기다릴지 명시할 수 있도록 해줍니다. 서버 사이드에서는, 서버가 특정한 RPC가 타임아웃됐는지 알아보거나 또는 RPC를 완료하기 위해 어느정도의 시간이 남았는지 알아볼 수 있습니다.

데드라인 또는 타임아웃을 명시하는 것은 언어에 따라 다르게 적용됩니다. 어떤 언어는 API에서 timeouts(특정 시간 이후)이라는 조건을 이용하고, 어떤 언어에서는 deadline(특정 시점 이후)이라는 조건을 이용합니다. 그리고 언어에 따라 timeouts 또는 deadline에 기본 값이 있을 수도 있고 없을 수도 있습니다.

RPC 종료

gRPC에서 클라이언트와 서버는 독립적이며 호출의 성공을 로컬에서 결정합니다. 서버와 클라이언트의 결과가 일치하지 않을 수도 있습니다. 이 말은 이를테면, 서버 사이드에서 RPC를 성공적으로 끝냈는데 (모든 응답을 성공적으로 보냄) 클라이언트에서는 실패(응답이 데드라인 이후에 왔음)할 수 있다는 것입니다. 서버가 클라이언트가 모든 요청을 보내기 전에 미리 완료되는 것도 가능하다는 얘기입니다.

RPC 취소

클라이언트 또는 서버가 RPC를 언제든 취소할 수 있습니다. 취소되면 RPG가 즉시 종료되고, 이후에 추가적인 작업들도 진행되지 않습니다.

경고: 취소 전에 생긴 변화는 롤백되지 않습니다.

메타 데이터

메타 데이터는 특정한 RPC 호출 (이를테면 인증 정보 세부사항)에 대한 정보이며 key-value 쌍으로 이루어져 있습니다. key는 문자열이고, value는 주로 문자열이 들어가지만, 이진 데이터가 들어가기도 합니다. 메타 데이터는 그 자체로는 gRPC와 통하지 않습니다. 메타데이터는 클라이언트가 호출과 관련된 정보를 서버에 전달하게 해주고 반대로도 동작합니다.

메타데이터에 대한 접근은 언어에 의존되어 있습니다.

채널

gRPC 채널은 명시된 hostport로의 gRPC 서버와의 연결을 제공합니다. 클라이언트 스텁을 만들 때 사용됩니다. 클라이언트는 메세지 압축을 키거나 끄는 등의 gRPC의 기본 행동을 제어하기 위해서 채널에 어떤 인자들을 명시할 수 있습니다. 채널은 상태를 가졌는데, connectedidle을 포함합니다.

gRPC가 닫힌 채널을 다루는 방법은 언어에 의존합니다. 어떤 언어들은 채널 상태를 질의하는 것을 허용합니다.

profile
풀스택 웹개발자로 일하고 있는 Jake Seo입니다. 주로 Jake Seo라는 닉네임을 많이 씁니다. 프론트엔드: Javascript, React 백엔드: Spring Framework에 관심이 있습니다.

0개의 댓글