@gbdx/rpc
v0.7.0
Published
RPC Helper
Readme
RPC
javascript 환경에서 사용할 수 있는 RPC Helper 라이브러리.
Modules
@gbdx/rpc (코어 + RN 어댑터)
- RpcClient — 클라이언트에서 RpcHost의 원격 프로시저를 호출할 수 있는 클라이언트 모듈
- RpcHost — RpcClient의 호출 요청을 통신 규약에 맞게 처리해서 돌려주도록 하는 서버 모듈
- RnWebviewRpcClient — react-native-webview용 RpcClient 구현체
- RnWebviewRpcHost — react-native-webview용 RpcHost 구현체
@gbdx/rpc/electron (Electron 어댑터)
- ElectronRpcClient — Electron 렌더러 프로세스용 RpcClient
- ElectronRpcHost — Electron 메인 프로세스용 RpcHost (ipcMain 자동 등록)
- exposeGbdxRpcBridge — preload script용 contextBridge helper
예제
- examples/electron — Electron main ↔ renderer 통신 데모.
@gbdx/rpc/electron어댑터로 procedure 호출과 main → renderer 단방향 이벤트 푸시를 보여줍니다.
Electron 사용법
가장 단순하게는 세 곳에 한 줄씩만 추가하면 끝납니다.
// preload.ts
import {exposeGbdxRpcBridge} from '@gbdx/rpc/electron'
exposeGbdxRpcBridge()// main.ts (메인 프로세스)
import {ElectronRpcHost} from '@gbdx/rpc/electron'
import {MyProcedures} from './procedures'
class MyHost extends ElectronRpcHost {
protected enumerateDependencies() {
return [MyProcedures] // procedure 클래스 import 트리거용
}
}
const host = new MyHost()
// host.emit(mainWindow.webContents, 'configChanged', {theme: 'dark'}) // 단방향 이벤트 푸시// renderer.ts (렌더러 프로세스)
import {ElectronRpcClient} from '@gbdx/rpc/electron'
import type {MyProcedures} from '../main/procedures'
const client = new ElectronRpcClient()
const proc = client.generateRpcProxy<typeof MyProcedures>({procedureClassName: 'MyProcedures'})
const result = await proc.add(1, 2)
client.on<{theme: string}>('configChanged', ({theme}) => { /* ... */ })BrowserWindow 생성 시 webPreferences.preload에 preload 스크립트 경로를 지정하세요. contextIsolation: true (Electron 기본값) 환경에서 동작합니다.
Requirements
Common
- Typescript: ^5.0.0
Babel 사용 시
- @babel/plugin-proposal-decorators ({version: '2023-11'})
- @babel/plugin-transform-class-static-block
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
['@babel/plugin-proposal-decorators', {version: '2023-11'}],
'@babel/plugin-transform-class-static-block'
],
}Changelog
0.6.1
수정
generateRpcProxy<typeof MyProcedures>(...)호출이 타입 에러를 내던 문제 수정.typeof Class는 메서드 외에prototype같은 필드를 포함하므로 기존ProcedureClass = Record<any, ProcedureMethod>제약을 만족 못 했음.ProcedureClass를object로 완화하고,ProcedurePromisify가 함수 시그니처를 가진 멤버만 골라 매핑하도록 변경. IDE 자동완성에서prototype등 noise도 제거됨.
0.6.0
추가
- Electron 어댑터 (
@gbdx/rpc/electron): RN 어댑터처럼 사전 구성된 Client/Host 제공ElectronRpcClient(렌더러) — preload bridge 자동 사용, 옵션 없이 바로 사용 가능ElectronRpcHost(메인) —ipcMainlistener 자동 등록,host.emit(webContents, ...)로 푸시exposeGbdxRpcBridge()— preload script용 contextBridge helperelectron은 optional peer dependency (RN 사용자에게는 영향 없음)
- base 변경:
RpcClient생성자가receiver()를 microtask로 defer 호출 → 자식 클래스 field/생성자 본문 실행 후에 receiver가 호출되어bridge같은 내부 상태를 안전하게 사용 가능. 기존RnWebviewRpcClient는 영향 없음 (receiver가 글로벌만 참조).
0.5.0
추가
이벤트 채널 (단방향 push): 응답이 필요 없는 fire-and-forget 알림 지원. RPC와 동일한 transport·channel 위에서 동작.
- 수신:
client.on(event, handler)/host.on(event, handler)— unsubscribe 함수 반환.off(event, handler?)로 직접 해제도 가능. - 발신 (Web → Native):
client.emit(event, payload) - 발신 (Native → Web):
(host as RnWebviewRpcHost).emit(webview, event, payload)— host는 transport별로 송신 대상이 다르므로 webview 참조를 매 호출마다 받음 (기존handle()과 일관)
// 웹 client.on<{lat: number; lng: number}>('locationChanged', ({lat, lng}) => { ... }) // 네이티브 host.emit(webview, 'locationChanged', {lat: 37.5, lng: 127.0})- 0.4의
__channel격리가 그대로 적용됨 (다른 channel의 이벤트는 무시). - 기존 RPC 메시지에는 영향 없음 —
event필드 유무로 분기.
- 수신:
0.4.0
기존 0.3.x 사용처는 코드 수정 없이 업그레이드 가능합니다.
추가
- call timeout:
ProxyOptions.timeout/RpcCallInfo.timeout(ms)이 지정되면 그 시간 내 응답이 없을 때 promise가RpcTimeoutError로 reject됩니다. 미지정 시 기존 동작 유지(무제한 대기). - 에러 직렬화 정규화: 호스트에서 throw된
Error/객체/원시값이{ name, message, stack? }구조로 직렬화되어 클라이언트가 에러 정보를 정상적으로 읽을 수 있습니다 (result.error.message).RpcResult.error타입이any→RpcErrorInfo | undefined로 좁아졌습니다.
- 외부 메시지 자동 필터링 + 채널 격리 옵션: 라이브러리가 모든 메시지에 채널 식별자(
__channel)를 자동 부착합니다. 기본값(RPC_DEFAULT_CHANNEL = '__GBDX_RPC__')이 적용되므로 사용처는 옵션을 안 줘도 자동 보호됩니다.- 커스텀 channel: 한 webview에 RPC 채널을 여러 개 띄우거나, 우연히 식별자가 충돌할 때 격리 가능
new RnWebviewRpcClient({channel: 'MY_APP'}) // Host도 동일 channel로 인스턴스화 new MyHost({channel: 'MY_APP'}) - 0.4 단계 동작: 기본 channel 사용 시 마킹 없는 피어 메시지는 콘솔 경고 후 그대로 처리(deprecation 윈도우). 커스텀 channel 사용 시 mismatch는 즉시 무시 (다른 채널 메시지로 간주, 응답 안 보냄).
- v1.0 예고: 기본 channel도 mismatch 시 차단으로 전환됩니다.
- 커스텀 channel: 한 webview에 RPC 채널을 여러 개 띄우거나, 우연히 식별자가 충돌할 때 격리 가능
수정
- procedure 미등록 시 에러 메시지가
procedure(undefined) not found로 출력되던 버그 수정 → 실제 procedure 이름이 표시됩니다.
호환성
| 변경 | 사용처 코드 수정 | 동작 변화 |
|---|---|---|
| timeout | 불필요 | 옵션 미사용 시 동일 |
| 에러 직렬화 | 불필요 | 기존엔 {}로 손실되던 게 정상화 |
| channel id | 불필요 | 0.4끼리는 자동 보호 / 구버전 피어와는 경고만 |
| 에러 메시지 버그 | 불필요 | 디버그 로그만 개선 |
