2025-08-11 03:56

Tags:

RPC 핸드북 원격 프로시저 호출의 모든 것

1. RPC, 왜 만들어졌을까?

분산 컴퓨팅의 서막

컴퓨터가 한 대가 아닌 여러 대로 늘어나면서, 서로 다른 컴퓨터에 있는 프로그램끼리 소통해야 할 필요성이 생김. 초창기에는 개발자들이 소켓(Socket) 프로그래밍을 통해 직접 네트워크 통신 코드를 일일이 작성해야 했음. 이는 매우 복잡하고 오류가 발생하기 쉬운 작업.

  • 데이터 전송 규약: 데이터를 어떤 형식으로 보낼지 약속해야 함.

  • 네트워크 연결 관리: 연결이 끊어지거나 지연되는 상황을 처리해야 함.

  • 오류 처리: 데이터가 유실되거나 순서가 뒤바뀌는 문제에 대응해야 함.

이러한 복잡성을 해결하고, “네트워크 통신의 구체적인 과정을 몰라도, 마치 내 컴퓨터에 있는 함수(프로시저)를 호출하는 것처럼 간단하게 원격지의 코드를 실행할 수 없을까?” 라는 아이디어에서 RPC가 탄생함.

2. RPC의 구조: 어떻게 작동하는가?

RPC의 핵심은 ‘네트워크 통신 과정을 추상화하여 개발자로부터 숨기는 것’. 이를 위해 클라이언트와 서버 양쪽에 ‘대리인’을 두는 방식을 사용함. 이 과정을 ‘해외 직구 대행 서비스’에 비유하여 이해할 수 있음.

핵심 구성 요소

  • Client: 원격에 있는 함수를 호출하는 쪽. (해외 물건을 구매하려는 ‘나’)

  • Server: 호출될 함수를 가지고 있는 쪽. (해외 현지 쇼핑몰)

  • Client Stub (스텁): 클라이언트 측의 대리인. 함수 호출을 받아 네트워크로 보낼 수 있는 메시지 형태로 가공(마샬링)함. (‘구매 대행 사이트’)

  • Server Skeleton (스켈레톤): 서버 측의 대리인. 네트워크로 받은 메시지를 서버가 이해할 수 있는 형태로 복원(언마샬링)하고, 실제 함수를 호출함. (‘현지 배송 대행업체’)

  • Marshalling (마샬링): 함수 호출에 사용된 파라미터(데이터)를 네트워크를 통해 전송할 수 있는 일련의 바이트(byte) 형태로 변환하는 과정. (구매 요청서를 ‘국제 운송장’ 양식에 맞게 작성하고 포장하는 것)

  • Unmarshalling (언마샬링): 네트워크를 통해 수신한 바이트를 원래의 데이터 형태로 복원하는 과정. (도착한 소포를 뜯어 ‘운송장’ 내용을 확인하는 것)

동작 과정 (해외 직구 비유)

  1. 함수 호출 (주문): 클라이언트가 calculate(10, 20)와 같은 함수를 호출. (내가 구매 대행 사이트에서 ‘A 운동화, 270mm’를 주문)

  2. 클라이언트 스텁의 마샬링 (주문서 작성 및 포장): 클라이언트 스텁이 이 호출을 가로채, calculate 함수와 파라미터 10, 20을 네트워크로 보낼 수 있는 특정 형식(예: 0x01, 0x0A, 0x14)으로 변환(마샬링)함. (구매 대행 사이트가 내 주문을 현지 업체가 알아볼 수 있는 코드로 변환하고 배송을 위해 포장)

  3. 네트워크 전송 (국제 배송): 포장된 데이터가 네트워크를 통해 서버로 전송됨. (포장된 물품이 비행기를 타고 해외로 배송)

  4. 서버 스켈레톤의 언마샬링 (포장 해체 및 내용 확인): 서버 스켈레톤이 데이터를 받아 원래의 함수 호출 정보(calculate, 10, 20)로 복원(언마샬링)함. (현지 배송 대행업체가 소포를 열어 주문 내용을 확인)

  5. 서버 함수 실행 (현지 구매): 스켈레톤이 복원된 정보를 바탕으로 서버에 있는 실제 calculate(10, 20) 함수를 실행. (현지 업체가 ‘A 운동화, 270mm’를 구매)

  6. 결과 반환 (역방향 배송): 실행 결과(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: 클라이언트가 함수를 호출한 뒤 결과를 기다리지 않고 바로 다음 작업을 수행하는 방식. 나중에 서버에서 결과가 오면 그 때 처리함. 시스템 전체의 효율성을 높일 수 있지만, 구현이 더 복잡함.

References

RPC