처리중입니다. 잠시만 기다려주세요.
TTJ 코딩클래스
정규반 단과 자료실 테크 뉴스 코딩 퀴즈
테크 뉴스
Hacker News 2026.04.21 22
#AI

Rust에서 Protobuf를 복사 없이 다루기, ConnectRPC가 여는 새로운 가능성

Hacker News 원문 보기

시작하며

Rust로 백엔드를 만들어 본 분들이라면 gRPC나 Protobuf를 한 번쯤 거쳐가셨을 거예요. 그런데 실제로 써보면 성능이 기대만큼 잘 나오지 않는 순간이 있어요. 특히 메시지가 크고 필드 수가 많을 때, 파싱과 메모리 복사 비용이 생각보다 크거든요. 이번에 Iain McGinniss가 공개한 글은 이 문제에 대한 꽤 흥미로운 접근을 보여줘요. Zero-copy Protobuf 파서와 ConnectRPC를 Rust에서 결합해서, 기존 tonic 기반 스택 대비 메모리 할당을 극적으로 줄이는 구현을 공유하고 있어요.

Zero-copy가 뭔데 왜 중요할까

일반적인 Protobuf 라이브러리, 예를 들어 prost 같은 건 바이트 버퍼를 받으면 그걸 한 번 훑어서 각 필드를 Rust의 String, Vec<u8>, 중첩 구조체 같은 소유 타입(owned type)으로 복사해요. 이러면 쓰기 편해요. 필드에 접근할 때마다 편하게 .name 이렇게 쓸 수 있거든요. 대신 비용이 커요. 메시지 하나에 문자열 필드가 10개 있으면, 파싱 시점에 10번의 String 할당이 일어나는 거죠.

Zero-copy 접근은 이걸 다르게 풀어요. 원본 바이트 버퍼를 그대로 들고 있으면서, 필드에 접근할 때만 그 버퍼의 특정 범위를 가리키는 뷰(view) 를 돌려줘요. 복사가 없어요. 문자열이 필요하면 원본 버퍼에서 잘라낸 &str을 주고, 바이트가 필요하면 &[u8] 슬라이스를 줘요. 할당이 거의 0에 가까워요. Cap'n Proto나 FlatBuffers가 이런 철학으로 유명한데, 이번 작업은 기존 Protobuf 스키마를 그대로 유지하면서도 이 방식을 적용했다는 점이 새로워요.

구현의 핵심은 코드 생성기를 손봐서, 필드 접근자가 오프셋만 기억하고 lazy하게 파싱하도록 만든 거예요. 반복 필드(repeated)도 이터레이터 기반으로 돌면서 필요할 때만 디코딩해요.

ConnectRPC는 또 뭐야

ConnectRPC는 Buf.build 팀이 만든 gRPC 호환 프로토콜이에요. 기본 아이디어는 이거예요. gRPC는 HTTP/2 트레일러와 커스텀 프레이밍을 쓰는데, 이게 브라우저나 일반 프록시에서 지원이 까다롭거든요. ConnectRPC는 평범한 HTTP/1.1 또는 HTTP/2의 POST 요청 하나로 단항 RPC를 보낼 수 있게 만들었어요. JSON과 Protobuf 양쪽을 지원하고, curl로도 호출할 수 있어요. 그러면서 gRPC 클라이언트와도 호환돼요.

이 글에서는 Rust용 ConnectRPC 서버/클라이언트를 직접 짜되, 그 위에 zero-copy Protobuf 디코더를 얹어서, 요청이 들어오자마자 필드에 접근하는 지연 없는 경로를 설계했어요. 벤치마크에서는 대용량 메시지를 다루는 핸들러에서 tonic + prost 대비 할당 횟수가 한 자릿수로 줄고, p99 레이턴시도 유의미하게 개선됐다고 보고해요.

업계 맥락: 직렬화 전쟁

사실 "복사 없는 직렬화"는 새로운 아이디어가 아니에요. Cap'n Proto를 만든 Kenton Varda가 이걸 주창한 지 10년이 넘었고, FlatBuffers는 게임 업계에서 널리 쓰이고 있어요. 최근에는 Meta의 thrift 최적화, Google의 Carbon, Apache Arrow 같은 프로젝트가 비슷한 철학을 공유해요. 다만 대부분은 새 스키마 언어를 배우라고 요구했어요. 이번 접근은 이미 조직이 축적한 .proto 파일을 그대로 쓸 수 있다는 점에서 실용적이에요.

비교하자면 Go 쪽의 vtprotobuf, C++ 쪽의 upb 같은 라이브러리가 유사한 방향으로 먼저 움직였어요. Rust는 상대적으로 늦었지만, 빌림(borrow)과 수명(lifetime) 시스템 덕분에 "어떤 뷰가 원본 버퍼보다 오래 살면 안 된다"는 안전성을 컴파일 타임에 보장할 수 있어요. 이건 다른 언어가 쉽게 흉내 내기 힘든 Rust만의 강점이에요.

한국 개발자에게 주는 시사점

대용량 gRPC 트래픽을 처리하는 국내 팀, 예를 들어 광고 입찰, 실시간 피드, 게임 서버, 금융 체결 엔진 쪽이라면 관심을 가질 만해요. 지금 tonic으로 운영 중인데 CPU의 20~30%가 파싱에 쓰이고 있다면, 이런 zero-copy 접근만으로 장비 수를 줄일 여지가 생겨요. 당장 프로덕션에 붙이기엔 아직 실험적이지만, proto 스키마 호환성을 유지한다는 점이 이식 비용을 크게 낮춰 줘요.

반대로 요청이 적고 메시지도 작은 일반 CRUD 서버라면 굳이 쫓아갈 필요는 없어요. 최적화는 병목이 있는 곳에만 쓰는 게 원칙이니까요. 다만 "데이터를 꼭 Rust 타입으로 옮겨야 하는가" 라는 질문은, RPC 외의 일반 코드에서도 성능을 생각할 때 유용한 사고 도구예요.

마무리

복사를 줄이는 건 결국 "필요할 때까지 일을 미룬다"는 lazy 철학의 구현이에요. Rust의 수명 시스템이 여기에 얼마나 잘 맞는지를 보여주는 좋은 사례이기도 하고요. 여러분의 백엔드에서 직렬화가 병목인 구간이 있나요? 있다면, 다음 성능 개선 카드로 이런 zero-copy 접근을 한 번 고민해 보시는 건 어떠세요?


🔗 출처: Hacker News

이 뉴스가 유용했나요?

이 기술을 직접 배워보세요

AI 도구, 직접 활용해보세요

AI 시대, 코딩으로 수익을 만드는 방법을 배울 수 있습니다.

AI 활용 강의 보기

"비전공 직장인인데 반년 만에 수익 파이프라인을 여러 개 만들었습니다"

실제 수강생 후기
  • 비전공자도 6개월이면 첫 수익
  • 20년 경력 개발자 직강
  • 자동화 프로그램 + 소스코드 제공

매일 AI·개발 뉴스를 받아보세요

주요 테크 뉴스를 매일 아침 이메일로 전해드립니다.

스팸 없이, 언제든 구독 취소 가능합니다.