프론트엔드 개발에서 gRPC가 자리 잡지 못한 이유
백엔드 개발자들은 네트워크 통신에 gRPC, Protobuf, Avro를 사용하는 데 익숙합니다. 하지만 프론트엔드로 넘어오면 REST는 번거로워집니다: 편리한 계약이 없고, Swagger는 양쪽에서 동기화가 필요합니다. JSON은 복잡성을 초래합니다—백엔드는 데이터를 마샬링하고, 프론트엔드는 변경으로 인한 문제를 걱정합니다. 요청은 resp?.body?[i]?.creds?.card?.number와 같은 체인으로 변합니다.
gRPC는 타이핑과 코드 생성으로 이러한 문제를 해결합니다. 그렇다면 왜 프론트엔드에서는 사용되지 않을까요?
OpenAPI와 Swagger에서의 코드 생성 문제
Swagger에서의 자동 생성은 안정성을 보장하지 않습니다. 백엔드 개발자가 필드를 변경하고 명세를 업데이트하는 것을 잊으면 프론트엔드가 깨집니다. 조직적 문제는 불가피합니다: 휴가, 긴급 업무.
Facebook의 GraphQL은 해결책을 약속했습니다: 엄격한 스키마, 인트로스펙션, 코드 생성. 프론트엔드 개발자는 혜택을 봤지만, 백엔드는 단점을 떠안았습니다:
- 클라이언트는 임의의 깊이를 요청할 수 있습니다:
{ user { id name } }에서 재귀적인posts { comments { author { ... } } }까지. - 데이터베이스 모델에 직접 매핑되지 않습니다—리졸버와 유니온 타입이 필요합니다.
- N+1 쿼리 문제.
DataLoader, 지속 쿼리, 깊이 제한은 백엔드에 복잡성을 더합니다. Go에서는 GraphQL 패키지가 특히 불편합니다.
gRPC-Web: 장점 없는 타협
gRPC-Web은 해결책처럼 보입니다: Protobuf, 코드 생성. 하지만 진짜 gRPC가 아닙니다.
브라우저는 HTTP/2+를 지원하지만, 완전한 제어는 없습니다:
- 연결, 프레임, 스트림 관리 없음—모든 것이
fetch('/api')를 통해 전달됩니다. - 브라우저 → 프록시는 HTTP/1.1, 프록시 → 백엔드는 HTTP/2. 이득은 백엔드에서만 발생합니다.
- 프록시 인프라가 필요합니다.
gRPC-Web은 전송이 아닌 데이터 형식이 됩니다. 장점은 사라집니다.
근본 문제: 브라우저 제한
브라우저는 보안상의 이유로 저수준 접근을 차단합니다. 웹사이트의 JS 코드는 네트워크 접근이 있지만, 완전한 HTTP/2+ 프레임은 다음을 허용할 수 있습니다:
- 로컬 네트워크 스캔.
- localhost 공격.
- 방화벽 우회.
- 사용자 연결을 통한 DDoS.
HTTP/1.1은 샌드박싱 덕분에 안전합니다: 소켓 없음, 제한된 fetch와 WebSocket. 브라우저는 HTTP/2+에서 멀티플렉싱과 헤더 압축을 자체 최적화를 위해 관리하며, JS를 위한 것이 아닙니다.
유망한 대안
해결책은 있지만, 보편적이지 않습니다:
- tRPC: TypeScript 모노레포용. 코드 생성 없이 타입을 직접 가져와 HTTP를 통해 사용합니다.
- Connect 프로토콜 (Buf): 브라우저에서 fetch를 위한 gRPC 상위 레이어, 코드 생성 포함.
- WebTransport: 샌드박스 내 HTTP/3 스트림을 위한 실험적 API. 미래 개발 방향입니다.
핵심 요약
- REST는 계약의 불편함에도 불구하고 보편성으로 인해 지배적입니다.
- 브라우저 샌드박스는 공격으로부터 보호하기 위해 저수준 HTTP/2+를 차단합니다.
- gRPC-Web은 스트리밍, 멀티플렉싱과 같은 핵심 기능을 잃습니다.
- tRPC, Connect, WebTransport는 특정 기술 스택을 위한 틈새 솔루션입니다.
- 업계는 WebTransport를 통한 샌드박스된 스트림 접근으로 나아가고 있습니다.
보편적인 계약이 등장할 때까지 REST는 표준으로 남을 것입니다. 디버깅에는 curl이 계속 사용될 것입니다.
— Editorial Team
아직 댓글이 없습니다.