cross-language-rpc

1 개의 포스트

cloudflare

Workers RPC, 이제 Python과 JavaScript 간에도 작동 (새 탭에서 열림)

Cloudflare Workers의 RPC가 이제 JavaScript/TypeScript와 Python 사이에서도 동작해, 서로 다른 언어로 작성된 Worker가 별도 API 스키마나 의존성 없이 메서드·객체·함수를 주고받을 수 있게 되었습니다. 개발자는 다른 언어의 Worker를 로컬 라이브러리처럼 호출할 수 있으며, 예외·비동기 반환값·콜백도 자연스럽게 전달됩니다. 이를 위해 Pyodide FFI와 사용자 정의 타입 변환 계층을 결합해 두 언어의 타입 체계를 연결했습니다. ## 언어 간 RPC 호출 - TypeScript Worker에서 정의한 `add(a, b)` 메서드를 Python Worker에서 `await rpc.add(42, 144)`처럼 호출할 수 있습니다. - 반대로 Python Worker의 메서드를 JavaScript/TypeScript에서 호출하는 것도 가능합니다. - 별도 패키지나 직렬화 스키마 없이 Service binding만 설정하면 됩니다. ```json { "services": [ { "binding": "RPC", "service": "ts-rpc-server", "entrypoint": "RpcService" } ] } ``` - RPC 대상은 Worker의 엔트리포인트 클래스에 정의된 메서드로 노출됩니다. ## 일반 함수처럼 동작하는 RPC - JavaScript/TypeScript에서는 Promise, Python에서는 Future처럼 비동기 결과를 받습니다. - 원격 메서드에서 발생한 예외는 호출한 쪽의 RPC 호출 지점에서 다시 발생합니다. - Structured Cloneable 타입을 인자와 반환값으로 전달할 수 있습니다. - JavaScript의 `Date`는 Python의 `datetime`으로 변환됩니다. - 숫자, 불리언, 객체, 배열 등 기본 타입도 대응되는 언어의 타입으로 변환됩니다. - 함수를 다른 Worker에 전달하거나 반환할 수 있습니다. - 상대 Worker가 해당 함수를 호출하면 원래 Worker로 역방향 RPC가 발생합니다. - 대부분의 Worker 간 RPC는 네트워크를 거치지 않고 동일한 스레드에서 실행되므로, 같은 Worker 내부 함수 호출에 가까운 성능을 제공합니다. - 구현은 `workerd`와 `workers-runtime-sdk`의 오픈 소스 코드로 제공됩니다. ## JavaScript와 Python의 호출 방식 차이 두 언어는 복잡한 인자를 표현하는 방식이 다릅니다. - JavaScript/TypeScript는 보통 객체를 전달합니다. ```ts myFunction({ key: "myKey", value: true, optional: 1 }); ``` - Python은 위치 인자와 키워드 인자를 사용합니다. ```python my_complex_function("myKey", True, optional=1) ``` - 목표는 호출자가 상대 언어의 내부 표현을 의식하지 않도록 만드는 것입니다. - Python에서 JavaScript 메서드의 옵션 객체를 다음 두 방식으로 모두 전달할 수 있습니다. ```python JSRPC.get("myKey", {"type": "text"}) JSRPC.get("myKey", type="text") ``` - Pyodide FFI가 두 호출을 JavaScript가 기대하는 옵션 객체 형태로 변환합니다. ## Pyodide FFI 기반 타입 변환 Pyodide는 WebAssembly로 컴파일된 CPython이며, Python과 JavaScript 사이의 기본 타입 변환 기능을 제공합니다. | Python 타입 | JavaScript 타입 | |---|---| | `int`, `float` | `Number` | | `bool` | `Boolean` | | `dict` | `Object` | | `list` | `Array` | - 직접 변환하기 어려운 사용자 정의 클래스나 함수는 Proxy 객체로 표현됩니다. - Proxy는 다른 언어의 속성 접근과 메서드 호출을 원격으로 전달합니다. - 이 방식으로 Python 함수를 JavaScript에 콜백으로 넘기는 등의 패턴을 구현할 수 있습니다. ## Cloudflare Workers 객체 처리의 과제 - `Request`, `Response`, `Blob`, `File` 같은 Cloudflare Workers의 Web API 객체는 일반 Python 타입과 달리 Pyodide가 자동 변환하지 못합니다. - 기본 동작에서는 이런 객체를 JavaScript Proxy로 전달합니다. - 기능적으로는 사용할 수 있지만, Python 개발자가 JavaScript 구현 세부사항과 Proxy를 계속 의식해야 하는 문제가 있습니다. - 따라서 언어 간 RPC를 완전히 자연스럽게 만들려면 표준 타입뿐 아니라 Workers 전용 객체에 대한 별도 변환 전략도 필요합니다. ## 실용적인 결론 언어별 강점을 활용해 하나의 Workers 애플리케이션을 구성하려는 경우, 이번 기능은 유용한 선택지입니다. Service binding만으로 TypeScript와 Python Worker를 연결할 수 있으므로, 공통 API 서버나 수동 직렬화 계층을 별도로 만들기보다 RPC를 통해 기능을 라이브러리처럼 분리하는 방식을 고려할 수 있습니다.