브라우저에서 gRPC 서비스를 호출해 본 경험이 있다면, 이미 그 어려움을 알고 계실 것입니다. 브라우저는 HTTP 트레일러를 제어할 수 없기 때문에 순수한 gRPC를 직접 사용할 수 없으며, 결국 트래픽 변환을 위해 Envoy와 같은 프록시를 추가해야 합니다. ConnectRPC는 이러한 단계를 없애줍니다. 이를 통해 브라우저가 직접 호출할 수 있고, 일반 curl 명령에 응답하며, 더 넓은 gRPC 생태계와 여전히 상호 운용되는 Protobuf 기반 API를 구축할 수 있습니다.
이 가이드에서는 ConnectRPC가 무엇인지, Connect 프로토콜이 해결하는 문제, Connect가 gRPC, gRPC-Web, REST와 어떻게 비교되는지, 그리고 HTTP를 통한 Connect 요청이 어떻게 생겼는지 설명합니다. 또한 표준 API 클라이언트를 사용하여 Connect 및 gRPC 엔드포인트를 테스트하고 디버그하는 방법도 살펴볼 것입니다.
ConnectRPC란 무엇인가
ConnectRPC는 Protocol Buffers를 사용하여 브라우저 호환 및 gRPC 호환 HTTP API를 구축하기 위한 라이브러리 제품군입니다. .proto 파일에서 서비스를 정의하고, 코드를 생성하며, 핸들러를 구현합니다. Connect는 라우팅, 직렬화, 압축 및 클라이언트 생성을 담당합니다.
이 프로젝트는 Protobuf용 buf 빌드 도구의 배후 기업인 Buf가 만들었으며, 현재는 Cloud Native Computing Foundation (CNCF) 샌드박스 프로젝트입니다. 이러한 배경은 중요합니다. Connect는 팀이 이미 buf 및 Protobuf와 함께 사용하는 스키마 우선 워크플로우에 맞게 설계되었습니다.
ConnectRPC 서버는 세 가지 프로토콜을 동시에 지원합니다.
- gRPC: 스트리밍 및 트레일러를 포함한 완벽한 호환성.
- gRPC-Web: 별도의 프록시가 필요 없는 직접 지원.
- Connect: 웹에 최적화된 자체 HTTP 기반 프로토콜.
하나의 서버가 이 세 가지를 모두 지원하므로 gRPC 클라이언트는 Connect 서버를 호출할 수 있고, Connect 클라이언트는 모든 gRPC 서버를 호출할 수 있습니다. 일반적으로 단일 구성 변경으로 코드 재작성 없이 클라이언트별로 프로토콜을 선택할 수 있습니다.
Connect가 해결하는 문제
gRPC는 빠르고 강력한 타입 지정을 제공하지만, 웹에서는 준수되지 않는 가정을 합니다. 상태 정보를 전달하기 위해 HTTP/2 및 HTTP 트레일러에 의존합니다. 브라우저는 JavaScript에 트레일러를 노출하지 않으므로, 브라우저는 네이티브 gRPC 클라이언트 역할을 할 수 없습니다. 일반적인 해결책은 gRPC-Web과 브라우저와 gRPC 백엔드 사이에 위치하는 Envoy와 같은 변환 프록시를 사용하는 것입니다.
이 방법은 작동하지만, 추가적인 구성 요소를 필요로 합니다. 이제 프록시를 실행하고 구성해야 하며, 추가적인 홉을 디버그해야 합니다. 이러한 오버헤드 없이 타입이 지정된 API와 브라우저 액세스를 원하는 팀에게는 설정이 필요 이상으로 복잡하게 느껴집니다.
Connect는 다른 접근 방식을 취합니다. 자체 프로토콜이 표준 HTTP를 통해 실행되므로 브라우저가 직접 호출할 수 있으며, 브라우저 트래픽을 위한 프록시가 필요하지 않습니다. 기존 gRPC 클라이언트를 지원해야 하는 경우에도 동일한 Connect 서버가 이를 처리합니다. 브라우저, 명령줄 도구 및 gRPC 서비스 모두에 응답하는 하나의 백엔드를 얻게 됩니다.
Connect vs gRPC vs gRPC-Web vs REST
이 네 가지 접근 방식은 서로 중첩되므로, 각자의 위치를 파악하는 것이 도움이 됩니다.
gRPC는 HTTP/2를 통해 바이너리 프레이밍 및 트레일러와 함께 Protobuf를 사용합니다. 효율적이며 모든 네 가지 스트리밍 모드를 지원하지만, 브라우저나 셸에서 호출하기에는 불편합니다. 전송 계층에 대한 복습이 필요하면, gRPC와 HTTP/2가 함께 작동하는 방식을 참조하십시오.
gRPC-Web은 gRPC의 브라우저 친화적인 변형입니다. 여전히 Protobuf를 중심으로 하며, 실제 gRPC 백엔드에 연결하기 위해 일반적으로 프록시가 필요합니다. gRPC-Web이 무엇인지에 대한 저희 가이드에서 그 위치를 다룹니다.
Connect는 Protobuf 스키마와 gRPC 스타일의 메서드 모델을 유지하지만, 해당 프로토콜은 HTTP/1.1, HTTP/2 및 HTTP/3에서 깔끔하게 실행됩니다. 단항 호출은 gRPC 바이너리 프레이밍 없이 일반 JSON 또는 Protobuf 본문을 전달하며, 응답은 실제 HTTP 상태 코드를 사용합니다. 이러한 조합 덕분에 Connect 호출은 어떤 REST 호출만큼이나 접근하기 쉽습니다.
REST는 리소스 지향적이며 스키마가 선택 사항입니다. 가장 보편적으로 지원되는 스타일이지만, Protobuf가 제공하는 코드 생성 및 엄격한 타입 지정이 부족합니다. 절충점을 고려하고 있다면, gRPC vs REST에서 그 차이점을 자세히 설명합니다.
요약하자면, Connect는 gRPC의 타입 지정 및 도구와 REST의 광범위한 접근성 및 디버깅 가능성을 제공하는 것을 목표로 합니다. 브라우저와 셸이 처리할 수 없는 부분을 제외하고 Protobuf 및 gRPC의 메서드 모델에 의존합니다.
HTTP를 통한 Connect 요청
Connect를 접근하기 쉽게 만드는 요소는 다음과 같습니다. 단항(unary) Connect 호출은 일반적인 HTTP POST입니다. URL 경로는 Protobuf 스키마에서 직접 가져오며, 본문은 추가 프레이밍 없이 JSON 또는 바이너리 Protobuf입니다.
경로 형식은 /<package>.<Service>/<Method>입니다. 따라서 greet.v1 패키지의 GreetService에 있는 Greet 메서드는 /greet.v1.GreetService/Greet에 위치합니다.
curl \
--header "Content-Type: application/json" \
--data '{"name": "Jane"}' \
http://localhost:8080/greet.v1.GreetService/Greet
응답은 일반 JSON입니다.
{"greeting": "Hello, Jane!"}
커스텀 클라이언트, 프록시, 바이너리 디코딩이 필요 없습니다. 이것이 전체 요청입니다. 본문이 실제 JSON이고 상태가 실제 HTTP 상태 코드이기 때문에 HTTP를 사용하는 모든 도구가 호출을 검사할 수 있습니다. 이것이 Connect 프로토콜을 원시 gRPC와 구분하는 특징이며, 원시 gRPC에서는 동일한 요청이 바이너리 프레이밍으로 래핑되고 트레일러에 상태를 전달합니다.
Connect는 단항 요청에 대해 두 가지 콘텐츠 타입을 지원합니다.
- 사람이 읽을 수 있는 JSON 페이로드용
application/json. - 압축된 바이너리 Protobuf용
application/proto.
더 작은 전송 크기를 원할 때는 바이너리 Protobuf를 보내고, 개발 중 가독성을 원할 때는 JSON을 보냅니다. 바이너리를 보내려면 헤더를 변경하고 인코딩된 본문을 전달합니다.
curl \
--header "Content-Type: application/proto" \
--data-binary @request.bin \
http://localhost:8080/greet.v1.GreetService/Greet
스트리밍 호출은 다른 콘텐츠 타입(application/connect+proto 또는 application/connect+json)을 사용하며, 각 메시지를 봉투(envelope)로 감쌉니다. 즉, 한 바이트의 플래그, 4바이트의 빅엔디안 길이, 그리고 메시지 순입니다. 단항 호출은 이 봉투를 완전히 건너뛰므로 일반 HTTP 요청에 매우 깔끔하게 매핑됩니다. 페이로드의 전송 형식(wire format)을 선택하는 경우, Protobuf vs JSON에서 크기와 가독성 간의 장단점을 다룹니다.
언어 지원 및 buf 도구
ConnectRPC는 여러 언어에 걸쳐 구현을 제공합니다. Go 및 TypeScript(브라우저 및 Node.js 모두 해당)는 안정적이고 프로덕션 준비가 완료된 구현체입니다. Swift는 Apple 플랫폼에서 사용할 수 있으며, Kotlin은 JVM 및 Android용이고, Python은 베타 버전입니다. 이러한 확장을 통해 클라이언트를 직접 작성할 필요 없이 Go 백엔드와 TypeScript 프런트엔드 간에 하나의 Protobuf 계약을 공유할 수 있습니다.
코드 생성은 buf 툴체인을 통해 실행됩니다. .proto 파일에 서비스를 설명한 다음, buf 플러그인을 사용하여 메시지와 Connect 핸들러를 생성합니다. Go 프로젝트는 Protobuf 메시지용 protoc-gen-go와 Connect 핸들러 및 클라이언트용 protoc-gen-connect-go 두 가지 플러그인을 사용합니다.
플러그인은 buf.gen.yaml 파일에 나열되며, 하나의 명령으로 생성을 실행할 수 있습니다.
buf generate
이는 타입이 지정된 메시지 구조체와 서비스용 서버 및 클라이언트 코드를 생성합니다. 거기서부터 핸들러 메서드를 구현하고 HTTP 서버에 등록합니다. 생성된 코드가 Go의 표준 라이브러리인 net/http를 대상으로 하므로 별도의 서버 런타임을 가져올 필요가 없습니다. Connect 핸들러는 기존 경로와 함께 마운트할 수 있는 일반적인 HTTP 핸들러입니다.
Connect 및 gRPC 엔드포인트 테스트 및 디버깅
Connect 단항 호출은 JSON 본문이 있는 일반 HTTP이므로, 다른 REST 엔드포인트를 테스트하는 것과 동일한 방식으로 테스트할 수 있습니다. 이는 실용적인 이점입니다. 개발 중에 서비스를 테스트하기 위해 특별한 클라이언트가 필요하지 않습니다.
Apidog에서는 Connect 단항 요청을 HTTP 요청으로 보냅니다. 메서드를 POST로 설정하고, http://localhost:8080/greet.v1.GreetService/Greet와 같은 스키마 파생 URL을 사용하며, Content-Type: application/json 헤더를 추가하고, 메시지를 JSON 본문에 넣습니다.
{"name": "Jane"}
JSON 응답과 실제 HTTP 상태 코드를 반환받으며, 이를 직접 확인할 수 있습니다. Apidog는 전용 Connect 클라이언트는 아니지만, 그럴 필요가 없습니다. curl이 하는 것과 동일하게 Connect 프로토콜이 노출하는 HTTP 인터페이스를 활용하며, UI, 저장된 요청 및 기록 기능이 추가됩니다. 관련 동사에 대한 간략한 설명은 HTTP 메서드란 무엇인가를 참조하십시오.
Connect 서버는 gRPC도 지원하므로, 서비스의 gRPC 측면도 테스트할 수 있습니다. Apidog는 gRPC 엔드포인트를 지원하므로 동일한 .proto 파일을 가져와 서비스 메서드를 탐색하고 타입이 지정된 요청으로 호출할 수 있습니다. 이는 하나의 도구가 서버의 두 가지 측면, 즉 HTTP 친화적인 Connect 프로토콜과 네이티브 gRPC 프로토콜을 모두 다룰 수 있음을 의미합니다. gRPC가 주요 관심사라면, gRPC API를 효율적으로 테스트하는 방법에서 워크플로우를 안내합니다.
요청이 제대로 작동하면, 이를 자동화된 검사로 전환할 수 있습니다. Connect 및 gRPC 호출을 테스트 시나리오로 저장한 다음, Apidog CLI를 사용하여 CI에서 실행하십시오. Node로 설치합니다.
npm install -g apidog-cli
그런 다음 환경을 지정하고 보고서 형식을 선택하여 저장된 시나리오 또는 스위트를 실행합니다.
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t <scenarioOrSuiteId> \
-e <environmentId> \
-r cli,html,junit
CLI는 헤드리스 방식이므로 Node를 실행할 수 있는 모든 CI 단계에 통합될 수 있습니다. 임시 요청을 보내는 대신 저장된 테스트 시나리오와 스위트를 실행하므로 Connect 및 gRPC 엔드포인트에 대한 회귀 검사에 적합합니다. 전체 워크스루는 명령줄에서 API를 테스트하기 위한 Apidog CLI 튜토리얼을 참조하십시오.
자주 묻는 질문
ConnectRPC는 gRPC와 동일한가요? 아닙니다. ConnectRPC는 gRPC, gRPC-Web, 그리고 자체 Connect 프로토콜의 세 가지 프로토콜을 구현하는 프레임워크입니다. Connect 서버는 gRPC 클라이언트 및 서버와 상호 운용되므로 gRPC 생태계에 적합하지만, Connect 프로토콜 자체는 브라우저와 셸이 직접 호출할 수 있는 별도의 HTTP 기반 설계입니다.
브라우저에 연결하기 위해 Envoy와 같은 프록시가 여전히 필요한가요? Connect 프로토콜의 경우에는 필요하지 않습니다. Connect는 표준 HTTP를 통해 실행되므로 브라우저는 변환 프록시 없이 Connect 서버를 호출할 수 있습니다. Envoy와 같은 프록시는 브라우저 트래픽을 네이티브 gRPC만 지원하는 백엔드로 연결해야 할 때만 필요합니다.
ConnectRPC는 어떤 언어를 지원하나요? Go 및 TypeScript(브라우저 및 Node.js)는 안정적이고 프로덕션 준비가 완료된 구현체입니다. Swift, Kotlin, Python도 사용할 수 있으며, Python은 베타 버전입니다. 이 모든 언어는 동일한 Protobuf 스키마에서 생성됩니다.
Connect와 buf의 관계는 무엇인가요? ConnectRPC는 Buf에서 생성되었으며, 코드 생성을 위해 buf 툴체인을 사용합니다. protoc-gen-connect-go와 같은 플러그인과 함께 buf generate를 실행하여 .proto 파일에서 핸들러와 클라이언트를 생성합니다.
일반 API 클라이언트로 Connect 엔드포인트를 테스트할 수 있나요? 네. Connect 단항 호출은 JSON 또는 Protobuf 본문과 실제 HTTP 상태 코드를 포함하는 HTTP POST 요청입니다. curl 및 Apidog를 포함한 모든 HTTP 클라이언트가 이를 보낼 수 있습니다. Apidog는 .proto 파일을 가져와 동일한 서버의 gRPC 측면도 호출할 수 있습니다.
