2025-08-11 03:56
Tags:
RPC 핸드북 원격 프로시저 호출의 모든 것
1. RPC, 왜 만들어졌을까?
분산 컴퓨팅의 서막
컴퓨터가 한 대가 아닌 여러 대로 늘어나면서, 서로 다른 컴퓨터에 있는 프로그램끼리 소통해야 할 필요성이 생김. 초창기에는 개발자들이 소켓(Socket) 프로그래밍을 통해 직접 네트워크 통신 코드를 일일이 작성해야 했음. 이는 매우 복잡하고 오류가 발생하기 쉬운 작업.
-
데이터 전송 규약: 데이터를 어떤 형식으로 보낼지 약속해야 함.
-
네트워크 연결 관리: 연결이 끊어지거나 지연되는 상황을 처리해야 함.
-
오류 처리: 데이터가 유실되거나 순서가 뒤바뀌는 문제에 대응해야 함.
이러한 복잡성을 해결하고, “네트워크 통신의 구체적인 과정을 몰라도, 마치 내 컴퓨터에 있는 함수(프로시저)를 호출하는 것처럼 간단하게 원격지의 코드를 실행할 수 없을까?” 라는 아이디어에서 RPC가 탄생함.
2. RPC의 구조: 어떻게 작동하는가?
RPC의 핵심은 ‘네트워크 통신 과정을 추상화하여 개발자로부터 숨기는 것’. 이를 위해 클라이언트와 서버 양쪽에 ‘대리인’을 두는 방식을 사용함. 이 과정을 ‘해외 직구 대행 서비스’에 비유하여 이해할 수 있음.
핵심 구성 요소
-
Client: 원격에 있는 함수를 호출하는 쪽. (해외 물건을 구매하려는 ‘나’)
-
Server: 호출될 함수를 가지고 있는 쪽. (해외 현지 쇼핑몰)
-
Client Stub (스텁): 클라이언트 측의 대리인. 함수 호출을 받아 네트워크로 보낼 수 있는 메시지 형태로 가공(마샬링)함. (‘구매 대행 사이트’)
-
Server Skeleton (스켈레톤): 서버 측의 대리인. 네트워크로 받은 메시지를 서버가 이해할 수 있는 형태로 복원(언마샬링)하고, 실제 함수를 호출함. (‘현지 배송 대행업체’)
-
Marshalling (마샬링): 함수 호출에 사용된 파라미터(데이터)를 네트워크를 통해 전송할 수 있는 일련의 바이트(byte) 형태로 변환하는 과정. (구매 요청서를 ‘국제 운송장’ 양식에 맞게 작성하고 포장하는 것)
-
Unmarshalling (언마샬링): 네트워크를 통해 수신한 바이트를 원래의 데이터 형태로 복원하는 과정. (도착한 소포를 뜯어 ‘운송장’ 내용을 확인하는 것)
동작 과정 (해외 직구 비유)
-
함수 호출 (주문): 클라이언트가
calculate(10, 20)
와 같은 함수를 호출. (내가 구매 대행 사이트에서 ‘A 운동화, 270mm’를 주문) -
클라이언트 스텁의 마샬링 (주문서 작성 및 포장): 클라이언트 스텁이 이 호출을 가로채,
calculate
함수와 파라미터10
,20
을 네트워크로 보낼 수 있는 특정 형식(예:0x01, 0x0A, 0x14
)으로 변환(마샬링)함. (구매 대행 사이트가 내 주문을 현지 업체가 알아볼 수 있는 코드로 변환하고 배송을 위해 포장) -
네트워크 전송 (국제 배송): 포장된 데이터가 네트워크를 통해 서버로 전송됨. (포장된 물품이 비행기를 타고 해외로 배송)
-
서버 스켈레톤의 언마샬링 (포장 해체 및 내용 확인): 서버 스켈레톤이 데이터를 받아 원래의 함수 호출 정보(
calculate
,10
,20
)로 복원(언마샬링)함. (현지 배송 대행업체가 소포를 열어 주문 내용을 확인) -
서버 함수 실행 (현지 구매): 스켈레톤이 복원된 정보를 바탕으로 서버에 있는 실제
calculate(10, 20)
함수를 실행. (현지 업체가 ‘A 운동화, 270mm’를 구매) -
결과 반환 (역방향 배송): 실행 결과(
30
)가 다시 스텁과 스켈레톤을 통해 마샬링/언마샬링 과정을 거쳐 클라이언트에게 최종적으로 전달됨.
3. RPC 사용법: 어떻게 구현하는가?
현대의 RPC는 **IDL(Interface Definition Language, 인터페이스 정의 언어)**을 사용하여 구현하는 것이 일반적. IDL은 클라이언트와 서버가 어떤 함수를 주고받을지 ‘계약서’처럼 미리 정의하는 언어.
IDL로 함수와 데이터 구조를 정의하면, 각 언어에 맞는 클라이언트 스텁과 서버 스켈레톤 코드가 자동으로 생성됨. 개발자는 자동 생성된 코드를 가져와 비즈니스 로직에만 집중하면 됨.
대표적인 프레임워크와 IDL
gRPC (Google RPC)
-
IDL: Protocol Buffers (프로토콜 버퍼). 텍스트(JSON, XML)보다 훨씬 가볍고 빠른 이진(binary) 형식을 사용.
-
특징: HTTP/2를 기반으로 하여 빠르고 효율적. 양방향 스트리밍 등 다양한 통신 방식 지원. MSA(마이크로서비스 아키텍처) 환경에서 각광받음.
// calculator.proto (Protocol Buffers IDL 예시)
// 서비스 정의: 계산기 서비스
service Calculator {
// Add 함수 정의: 두 숫자를 더함
rpc Add (AddRequest) returns (AddResponse);
}
// 요청 메시지 구조
message AddRequest {
int32 number1 = 1;
int32 number2 = 2;
}
// 응답 메시지 구조
message AddResponse {
int32 sum = 1;
}
Apache Thrift
-
IDL: Thrift IDL
-
특징: 페이스북(현 메타)에서 개발. C++, Java, Python 등 매우 다양한 프로그래밍 언어를 지원하는 것이 큰 장점.
JSON-RPC / XML-RPC
-
IDL: 별도의 IDL 없이 JSON 또는 XML 형식 자체를 사용.
-
특징: 구현이 매우 간단하고 사람이 읽기 쉬움. 하지만 gRPC나 Thrift에 비해 성능과 기능 면에서는 한계가 있음.
4. 심화 내용: RPC 더 깊게 이해하기
RPC vs. REST API
종종 RPC와 비교되는 대상은 REST API. 둘은 서버와 통신하는 방식이지만, 철학에 근본적인 차이가 있음.
구분 | RPC (Remote Procedure Call) | REST (Representational State Transfer) |
---|---|---|
핵심 철학 | ’동사(Verb)’ 중심 | ’명사(Noun)’ 중심 |
관점 | 원격에 있는 **‘함수(기능)‘**를 어떻게 호출할 것인가? | 웹에 존재하는 **‘자원(Resource)‘**을 어떻게 표현하고 다룰 것인가? |
예시 | getUser(userId: 123) updateUser(user: {...}) | GET /users/123 PUT /users/123 |
장점 | 직관적인 함수 호출 방식, 성능(특히 gRPC) | HTTP 표준을 그대로 활용, 범용성, 느슨한 결합 |
단점 | 클라이언트-서버 간 강한 결합 | 특정 기능에 여러 번의 요청이 필요할 수 있음 |
언제 무엇을 선택할까?
-
RPC: 내부 시스템 간의 고성능 통신이 필요할 때 (예: MSA 내부 서비스 간 통신)
-
REST: 외부에 공개되는 개방형 API, 웹 브라우저와의 통신이 중요할 때
동기 vs. 비동기 RPC
-
동기(Synchronous) RPC: 클라이언트가 함수를 호출하고 서버로부터 응답이 올 때까지 기다리는 방식. 구현은 간단하지만, 서버 응답이 늦어지면 클라이언트 전체가 멈출 수 있음.
-
비동기(Asynchronous) RPC: 클라이언트가 함수를 호출한 뒤 결과를 기다리지 않고 바로 다음 작업을 수행하는 방식. 나중에 서버에서 결과가 오면 그 때 처리함. 시스템 전체의 효율성을 높일 수 있지만, 구현이 더 복잡함.