RPC란?
- Remote Procedure Call의 약자로, 현재 실행 중인 프로세스의 주소 공간에서 호출하는 것이 아니라, 외부의 프로세스와 상호작용하기 위한
프로토콜이다.
- 즉, 네트워크를 통해 다른 프로세스와 상호작용 하는
IPC의 일종이라고 볼 수 있다.
- 네트워크로 외부의 프로세스와 상호작용하기 위한
프로토콜은 가장 대표적으로 REST API가 있다.
- 그렇다면
REST API와의 차이점은 무엇인가?
- Rest API는 자원을 HTTP 메소드 (GET, POST 등)으로 구분해서 요청하는 구조이며, RPC는 원격의 함수를 마치 로컬에 있는 함수처럼 호출해 결과를 가져오는 방식이다.
- 실제 RPC자체는 1980년대부터 존재하는 기술이었고 계속 사용되었던 기술이다.
- REST API가 익숙한 베이비 개발자 입장에서는
REST API 가 더 최근에 만들어진 개념인게 약간 놀랍기는하다.
함수 vs 프로시저
- 함수: input에 따른 output의 발생을 목적으로 한다. 즉, return값이 필수
- 프로시저: output에 집중하기 보다는
명령 단위가 수행하는 절차에 집중한 개념
필요성
- 그냥 통상적으로 많이 쓰는
REST API를 사용하면 되는 것 아닌가? 왜 필요한 기술인건가?
- 소프트웨어 개발에서는 하나의 서비스를 만들기 위해서 각 기능의 요구에 따라 다양한 언어와 프레임워크를 사용하는 경우가 많다.

- 또한, 최근
MSA구조가 사용되면서, 하나의 서비스에서도 다양한 프로세스 간에 통신하는 것이 필요하다.
- 서로 다른 프로세스에서 실행 중인 서버 혹은 프로그램 간에 동일한 방식으로 통신하기 위해서는 메시지 포맷이나 오류 처리 등을 각각 작성해 줘야한다.
- RPC는
Client-Server간의 커뮤니케이션에 필요한 정보는 최대한 감추고, 일반 메소드를 호출하는 것처럼 다른 프로세스의 프로시저를 호출하는 것에 목적을 둔다.

- 이런 복잡함을 개선하기 위해서 각기 다른 환경에서도 동일하게 적용 가능하고 단순화 할 수 있는
RPC가 유용한 것이다.
작동 원리
- RPC는 크게
IDL (Interface Definition Language)를 이용한 방식과 이를 사용하지 않는 방식으로 분류된다.
- IDL은 클라이언트와 서버간의 인터페이스를 정의하는 언어인데, 이를 사용하지 않는 경우 네트워크와 관련된 처리를 직접 해줘야한다는 차이가 존재한다.
- 클라이언트 프로세스는 서버의 함수를 호출하기 위해 사전에
IDL 로 작성된 (혹은 수동으로 정의한) 클라이언트의 Stub 에 존재하는 함수를 호출한다.
- 이때, Stub은 서로 다른 환경의 프로세스를 호출하기 위해 정의한
추상화 객체이다.
- 이때, Stub은 원격 호출을 위해
함수의 매개변수를 직렬화한다, 이는 데이터를 네트워크 전송이 가능하도록 변환하는 과정이며 이를 Marshalling이라고 한다.
- 이진 형식, JSON, 프로토콜 버퍼와 같은 포맷을 사용
- 이후 마샬링된 데이터는 네트워크를 통해 서버에 전송된다.
- 서버는 해당 데이터를 받고, 다시 서버에서 사용 가능한 형태로 복원하는데, 이를
Unmarshalling이라고 한다.
- 해당 언마샬링된 데이터와 함께 서버 스텁에서 서버의 함수를 호출하고, return 값이 있다면 다시 클라이언트에 전송할 수 있도록 마샬링을 수행한다.
- 이후 마샬링된 결과를 같은 과정으로 다시 클라이언트에게 전달.
장단점
장점
- 앞서 말했듯이 네트워크 통신의 복잡성을
추상화하여 각기다양한 환경에서도 쉽게 커뮤니케이션을 할 수 있다.
- RPC는 JSON 포맷이 아니라,
이진 직렬화 혹은 프로토콜 버퍼 (gRPC)를 사용하는데, 이는 데이터의 크기가 줄어들어 데이터 전송 속도가 빠르다.
단점
- 서버와 클라이언트가 사전에
정의된 인터페이스 (IDL)에 강하게 의존하기에, 변화에 따라 서버와 클라이언트 모두 대응해줘야 한다.
- 함수처럼 호출하지만, 엄밀히
네트워크 통신을 통해 이루어지므로, 해당 과정에서 발생하는 직렬화, 역직렬화, 네트워크 등의 문제를 겪을 수 있다.
gRPC
개요
- gRPC에서 클라이언트는 네트워크 상의 다른 서버의 메서드를
로컬 객체처럼 호출할 수 있다.
- 다른 RPC 시스템과 마찬가지로 gRPC는 원격 호출이 가능한 서비스를 정의하고, 호출할 메서드와 매개변수, 반환 타입을 명시하는 방식으로 이루어진다.
- 서버측에서는 이러한
인터페이스를 구현하고, gRPC 서버를 실행해서 클라이언트의 요청을 처리한다.

Protocol Buffers
- gRPC는
Protocol Buffers를 사용해서 데이터를 직렬화한다.
- 이전에 RPC에서 소개했던 마샬링과 언마샬링에서 사용되는 포맷이 gRPC에서는
Protocol Buffers인 것이다.
- 먼저
proto파일에서 직렬화할 데이터의 구조를 정의하며, 각 메시지는 이름과 값 쌍으로 구성된 여러 필드로 구성된다.
message Person {
string name = 1;
int32 id = 2;
bool has_ponycopter = 3;
}
- 이렇게 데이터 구조를 정의한 후에,
프로토콜 버퍼 컴파일러 (protoc)를 사용해 proto정의에서 데이터를 접근할 수 있는 class code를 생성한다.
- 아래 사진을 보면, 필드 번호, 필드 유형등을 1byte로 받아서 식별하고, 정해진 length만큼 읽도록 해서 단지 33 byte만 소요되는 장점을 볼 수 있다.

gRPC Service
// Greeter 서비스 정의
service Greeter {
// 인사 전송
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// 요청 메시지에 사용자 이름을 포함
message HelloRequest {
string name = 1;
}
// 응답 메시지에 인사 메시지 포함
message HelloReply {
string message = 1;
}
- gRPC 서비스 정의는 일반 proto 파일에서 정의할 수 있으며, RPC 메서드의 매개변수와 반환 타입을 프로토콜 버퍼 메시지로 지정해서 생성한다.
Service Methods
- gRPC에는 4가지 유형의 서비스를 지원한다.
- 양방향 통신 및 스트리밍도 가능하다는 점이 큰 장점이라고 느껴진다.
- 이는 gRPC가
HTTP/2 기반으로 통신하기에, 동시에 데이터를 스트리밍으로 주고받을 수 있는 것이다.
- Unary RPC : 클라이언트가 서버에 단일 요청을 보내고 단일 응답을 받는다.
rpc SayHello(HelloRequest) returns (HelloResponse);
- Server streaming RPC : 클라이언트가 서버에 요청을 보내면, 서버가 여러 응답을 순차적으로 전송할 수 있다.
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
- Client streaming RPC : 클라이언트가 서버에 여러 요청을 전송하고, 서버가 한 번에 응답을 보낸다.
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
- Bidirectional streaming RPC : 클라이언트와 서버가 서로 독립적으로 메시지 스트림을 주고받을 수 있다.
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
장단점
- gRPC는 아래와 같이 뚜렷한 장단점을 가지고 있다.
- 하지만 브라우저가 불필요한 분산 환경에서는
속도와 Protobuf를 사용한 처리 효율에서 굉장한 강점을 보인다.
장점
- 네트워크 요청을 하기위해 마샬링과, 언마샬링을 하는데 이 과정에서 Protobuf를 사용하기에 JSON보다 훨씬 빠르다.
- 내부적으로 HTTP/2를 기반으로 하기에,
헤더 압축 및 양방향 스트림 통신이 가능하다.
단점
- 브라우저 환경에서 사용할 수 없다. 이는 HTTP/2와 Protobuf를 사용하기에 브라우저와 호환되지 않아 사용할 수 없다.
- 직접 구축해보지는 않았기에, 직접 와닿지는 않지만 REST보다 구현과 구축이 더 복잡한 단점이 존재한다고 한다.