RPC 아키텍처와 원격 호출의 처리 방식
RPC의 호출 구조와 Stub, 마샬링·언마샬링, 바인딩, 호출 의미론을 중심으로 주요 구현과 운영 요소를 정리한다.
2026-08-15 · 최초 발행 2026-01-12
함수 호출 뒤에서 일어나는 네트워크 통신
RPC(Remote Procedure Call)는 다른 컴퓨터에 있는 프로시저나 함수를 로컬에서 실행하는 것처럼 호출하게 하는 분산 컴퓨팅 기술이다. 호출 코드는 네트워크 통신의 세부 처리를 직접 다루지 않아도 되며, 분산 애플리케이션 개발 과정도 단순해진다.
로컬 프로시저 호출은 같은 프로세스 안에서 이뤄진다. 반면 원격 프로시저 호출은 네트워크를 넘어 다른 프로세스나 머신의 함수를 실행한다. RPC는 이 차이를 호출자에게 감추는 위치 투명성을 제공하며, 동기적 호출 모델을 특징으로 한다. Bruce Jay Nelson이 1981년 Xerox PARC에서 제시한 개념이기도 하다.
IPC(Inter-Process Communication)가 프로세스 간 메시지 전달, 공유 메모리, 파이프, 소켓을 포괄한다면 RPC는 그중 네트워크를 경유하는 고수준의 함수 호출 인터페이스에 가깝다. 분산 컴퓨팅 환경에서 통신 세부사항을 어느 정도 감춘 채 서비스를 분리하기 위해 사용한다.
Stub과 Runtime이 호출 경로를 나눈다
클라이언트가 호출을 시작하면 Client Stub, Runtime Library, 네트워크, Server Stub을 거쳐 실제 서비스로 전달된다. 반환 결과는 같은 경로를 반대로 통과한다.
| 구성요소 | 역할 |
|---|---|
| Client | 서비스 요청자 |
| Client Stub | 클라이언트 측 프록시, 마샬링 담당 |
| Server Stub | 서버 측 프록시, 언마샬링 담당 |
| Server | 실제 서비스 제공자 |
| Runtime | 통신 및 바인딩 처리 |
| IDL Compiler | 인터페이스 정의에서 Stub 생성 |
전송 데이터로 바꾸고 다시 복원한다
마샬링은 매개변수를 전송 가능한 형태로 직렬화하는 과정이다. 구조화된 데이터는 바이트 스트림으로 변환되며, 이때 바이트 순서, 패딩, 포인터를 고려한다.
수신 측의 언마샬링은 바이트 스트림을 원래 매개변수 형태로 역직렬화한다. 데이터 타입과 범위 확인도 이 단계에서 이뤄진다.
| 표현 방식 | 설명 | 예시 |
|---|---|---|
| XDR | External Data Representation | Sun RPC |
| NDR | Network Data Representation | DCE RPC |
| CDR | Common Data Representation | CORBA |
| Protocol Buffers | 바이너리 직렬화 | gRPC |
서버 위치를 정하는 바인딩 방식
정적 바인딩에서는 컴파일 시점에 서버 주소를 결정한다. 성능과 단순성이 장점이지만, 서버 위치 변경에 유연하게 대응하기는 어렵다.
동적 바인딩은 런타임에 서버 위치를 찾는다. 서버가 Binder 또는 Registry에 서비스를 등록하고, 클라이언트는 그곳에서 서버 주소를 조회한 뒤 RPC를 호출한다. 유연성과 부하 분산 가능성이 있는 대신 오버헤드가 따른다.
호출 보장과 장애를 함께 다뤄야 한다
RPC는 네트워크를 통과하므로 호출이 몇 번 실행됐는지, 실제 실행됐는지 알 수 없는 상황을 고려해야 한다.
| 의미론 | 설명 | 특징 |
|---|---|---|
| At-most-once | 최대 한 번 실행 | 중복 실행 방지 |
| At-least-once | 최소 한 번 실행 | 멱등 연산에 적합 |
| Exactly-once | 정확히 한 번 실행 | 구현 복잡 |
| Maybe | 실행 여부 불확실 | 가장 단순 |
클라이언트, 서버, 네트워크 중 어느 곳에서 장애가 발생했는지에 따라 처리 방식도 달라진다. 고아 처리는 클라이언트 장애와 연결되고, 서버 장애에는 타임아웃과 재시도를, 네트워크 장애에는 중복 감지를 고려한다.
구현 계보와 gRPC의 통신 구조
Sun Microsystems의 Sun RPC(ONC RPC)는 XDR 데이터 표현과 Portmapper를 사용하며 NFS, NIS 같은 Unix 시스템에서 활용됐다. DCE RPC는 OSF(Open Software Foundation)가 개발했고 NDR 데이터 표현과 UUID 기반 구조를 특징으로 하며 Microsoft RPC의 기반이 됐다.
XML-RPC와 SOAP은 HTTP를 전송에 사용하고 XML 데이터를 다룬다. 방화벽 친화적인 웹 서비스 방식이라는 특징이 있다.
gRPC는 HTTP/2를 프로토콜로 사용하고 Protocol Buffers로 직렬화한다. 양방향 스트리밍과 다중 언어 지원을 제공한다.
REST와 다른 선택 기준
| 항목 | RPC | REST |
|---|---|---|
| 패러다임 | 동작 중심 | 자원 중심 |
| 결합도 | 강결합 | 약결합 |
| 프로토콜 | 다양 | HTTP |
| 성능 | 높음 (바이너리) | 중간 (텍스트) |
| 발견성 | 낮음 | 높음 |
| 캐싱 | 어려움 | 용이 |
프레임워크별 인터페이스 표현
IDL(Interface Definition Language)은 함수 시그니처와 데이터 타입, 서비스 계약을 명세하는 언어 중립적이고 플랫폼 독립적인 표현이다. 이 정의를 바탕으로 클라이언트와 서버에서 사용할 Stub 코드를 생성할 수 있으며, 서로 다른 언어로 작성된 구성 요소도 같은 인터페이스 계약 아래 통신할 수 있다.
// IDL 예시
interface Calculator {
int add(int a, int b);
int subtract(int a, int b);
double divide(double a, double b);
}
gRPC에서는 Protocol Buffers로 서비스와 메시지를 정의할 수 있다.
syntax = "proto3";
service Calculator {
rpc Add(AddRequest) returns (AddResponse);
rpc StreamCalculate(stream CalcRequest) returns (stream CalcResponse);
}
message AddRequest {
int32 a = 1;
int32 b = 2;
}
message AddResponse {
int32 result = 1;
}
Apache Thrift는 Facebook에서 개발돼 Apache로 이어졌으며, 다중 언어와 다중 프로토콜을 지원한다. 대규모 서비스 간 통신에 사용된다.
Apache Avro는 스키마 진화와 동적 타이핑을 특징으로 하며 Hadoop 생태계에서 사용된다.
연결과 데이터 전송을 조정하는 방법
연결 재사용을 위한 연결 풀링, 연결을 유지하는 Keep-Alive, 단일 연결에서 다중 요청을 처리하는 멀티플렉싱은 연결 관리에 사용된다. 데이터 측면에서는 압축, 배치 처리, 비동기 호출, 캐싱을 적용할 수 있다.
비동기 RPC는 결과를 받은 뒤 콜백을 호출하는 방식, Future/Promise로 비동기 결과를 다루는 방식, 데이터를 연속 전송하는 스트리밍 방식으로 구성할 수 있다.
인증과 권한 부여의 범위
| 방식 | 설명 |
|---|---|
| TLS/mTLS | 전송 계층 암호화 및 상호 인증 |
| Token 기반 | JWT, OAuth 토큰 |
| 인증서 | X.509 인증서 |
권한 부여는 ACL, RBAC, 메서드 수준 제어로 구성할 수 있다. 메서드 수준 제어에서는 프로시저별 권한을 다룬다.
서비스 간 통신과 분산 환경
마이크로서비스에서는 API Gateway가 User Service, Order Service, Payment Service에 연결되고 서비스끼리 gRPC로 통신하는 구성이 가능하다.
분산 파일 시스템의 NFS, 분산 데이터베이스 노드 간 통신, Kubernetes API를 통한 클러스터 관리는 RPC가 적용되는 대표적인 분산 시스템 영역이다.