Java-Python 음성 경계를 gRPC 계약으로 고정하기
Java API와 Python 음성 엔진은 서로 다른 프로세스이므로, 문자열 기반 내부 호출보다 protobuf 계약이 변경과 장애를 더 분명하게 만든다. voice/v1/voice.proto는 음성 합성·voice catalog·capability를 하나의 버전 경계로 묶고, Java client는 요청 deadlin…
목차
Java API와 Python 음성 엔진은 서로 다른 프로세스이므로, 문자열 기반 내부 호출보다 protobuf 계약이 변경과 장애를 더 분명하게 만든다. voice/v1/voice.proto는 음성 합성·voice catalog·capability를 하나의 버전 경계로 묶고, Java client는 요청 deadline을 넘기지 않는다.
경계를 넘는 한 번의 합성 요청
브라우저는 안정적인 REST 계약으로 Java API를 호출합니다.
Java는 크기·권한·request ID를 확정합니다.
protobuf 요청을 deadline과 함께 Python 엔진에 보냅니다.
실패 종류와 멱등성을 확인한 뒤에만 제한된 대체 경로를 사용합니다.
계약의 핵심
Synthesize는 provider, text, voice, request ID를 받고 audio bytes와 content type, duration, provider를 반환한다.- Python server는 텍스트·request ID·메시지 크기를 제한하고, provider 예외 본문이나 입력 text를 외부 오류로 복사하지 않는다.
- Java client의 blocking stub은 bounded elastic 실행기에서 실행하며, gRPC가 꺼져 있거나 실패하면 기존 REST TTS 경계로 명시적으로 fallback한다.
- public REST API는 유지한다. gRPC는 내부 서비스 간 비용·계약 경계이며, 모든 API를 gRPC로 바꾸는 목표가 아니다.
전송 스위치와 비용 승인을 분리한다
gRPC transport가 준비됐다는 사실은 유료 합성을 실행해도 된다는 뜻이 아니다. 공개 REST, 내부 gRPC, fallback이 같은 provider를 호출한다면 모든 경로가 하나의 비용 승인 조건을 공유해야 한다.
effective voice = transport enabled AND server TTS approved
| 경로 | 자체 조건 | 반드시 공유할 조건 |
|---|---|---|
| 공개 REST | HTTP endpoint 활성화 | server TTS 비용 승인 |
| 내부 gRPC | gRPC server 활성화 | server TTS 비용 승인 |
| REST fallback | fallback 대상 정상 | server TTS 비용 승인과 멱등성 |
Compose의 producer와 consumer 모두 기본값을 false로 둔다. 한쪽의 transport flag만 켜도 capability가 열리거나 provider가 호출되면 우회다. fallback도 상위 경로보다 권한을 넓히지 않고 같은 gate를 다시 확인해야 한다.
완료 기준
- proto 생성 코드가 Java와 Python 빌드에서 같은 source를 사용한다.
- deadline 초과·provider 오류·gRPC 비활성화가 안전한 오류 종류와 REST fallback으로 관측된다.
- Spring MDC의 요청 ID가 있으면 protobuf
request_id로 전달하되, 고카디널리티 사용자 입력을 로그 키로 만들지 않는다. GetCapabilities와/health/capabilities가 실제 server lifecycle과 일치한다.- 유효 Compose 설정에서 transport와 비용 gate가 모두 기본 차단이고, 어느 공개·내부·fallback 경로도 provider를 호출하지 않는다.
경계 선택표
| 호출 | 적합한 경계 | 이유 | 필수 가드 |
|---|---|---|---|
| 공개 브라우저 API | REST | 캐시·디버깅·호환성 | 인증, rate limit |
| 내부 짧은 RPC | unary gRPC | 타입·deadline | 크기 제한, fallback |
| 긴 생성 작업 | job/queue | 요청 수명 분리 | 멱등 키, 상태 조회 |
| 실시간 미디어 | WebRTC | 미디어 전송 최적화 | 비용 gate, 세션 상한 |
browser ─REST─▶ Java API ─gRPC(deadline)─▶ Python engine
└─failure─▶ bounded REST fallback
fallback은 동일 요청을 무조건 두 번 실행하지 않아야 합니다. 합성처럼 비용이 드는 작업은 gRPC 응답을 받지 못했다고 실패가 확정된 것이 아니므로 request ID와 provider의 멱등 계약을 확인한 뒤 재시도합니다.