25P by disjukr 2022-04-06 | favorite | 댓글 10개

산타토익을 서비스중인 뤼이드에서는 gRPC/Protobuf를 아주 활발하게 사용하고 있습니다.
제가 뤼이드에 입사하고 얼마 지나지 않았을 무렵, 앞으로 백엔드 팀에서 프론트엔드(모바일/웹)에 제공하는 모든 API는 gRPC로 통일될 것이라는 통보를 받았습니다.

웹 프론트엔드에서 gRPC/Protobuf 스택을 사용하려면 기존에는 protoc에 JS/TS 플러그인을 붙여서 사용하거나 Protobuf.js를 이용하는 방법이 있었습니다.

protoc의 공식 JS 플러그인은 아주 오래된 스타일의 코드를 생성하는 문제가 있었고, 생태계 플러그인들 또한 저희 요구사항을 전부 충족하지 못했습니다. 네이티브 바이너리(protoc) 의존성이 따라다닌다는 불편함도 있었고요. (요즘에는 M1 장비에서 protoc를 설치하기 어려운 문제도 있습니다.)

저희는 Protobuf.js를 사용해서 그 동안 여러 제품들을 만들었는데, 회사에서 만들어지는 모든 제품에 대해서 플랫폼간 소통하는 모든 인터페이스를 Protobuf를 사용하다보니 Protobuf.js가 저희가 필요로 하는 수준만큼 성숙하지 않다는 것을 알게되었습니다.
메세지 이름이 같으면 다른 네임스페이스에 들어있는 메세지로 오인하는 경우가 있거나, 전역 네임스페이스에서 enum 다음에 메세지 선언이 따라오면 메세지 타입 코드 생성이 안된다거나, 타입스크립트 타입 정의가 생성된 JS 동작과 다르다거나 하는 등의 여러 문제를 밟았습니다.

이 과정에서 특정 제품에 필요한 protobuf 스키마만을 추려서 빌드하는 시스템을 구성하기 위해 pollapo라는 protobuf 패키지 매니저를 만들었습니다.
(당시에 다른 protobuf 의존성 관리자들이 있었으나 버그가 있거나, nested 의존성을 지원하지 않는 문제 등이 있었습니다. 또한 buf에서 제공하는 패키지 관리 기능은 당시에 개발중이라는 블로그 포스트만 있는 상태였고, 저희가 pollapo를 만들고 내부 마이그레이션을 완료할 때까지 완성이 안 된 상태였습니다.)

pollapo를 이용해서 제품당 빌드하는 스키마 갯수를 크게 줄였고, 같은 메세지 이름 등으로 인해서 발생하는 버그는 줄었지만 그럼에도 여전히 버그와 빌드 문제 등이 존재했고, 이를 해결하기 위해 protobuf to typescript 컴파일러를 직접 만들었습니다.

산타토익은 현재 protobuf.js를 전부 걷어내고 pbkit으로 교체를 완료한 상태입니다.


산타토익을 포함해서 뤼이드에서 개발되는 앱들은 웹뷰를 활발하게 사용합니다.
웹뷰는 기기/사용자 정보나 현재 보여주는 컨텐츠 정보를 얻어오기 위해 네이티브와 통신을 하는데, 이 때의 인터페이스 또한 Protobuf 서비스 스키마를 사용해서 정의합니다.

pbkit에서는 서비스 코드 생성 시에 네트워크 레이어를 gRPC 대신 다른 프로토콜로 교체할 수 있는 인터페이스를 제공합니다.
pbkit 컴파일러를 이용하는 웹 프론트엔드 엔지니어들은 모바일 네이티브와 통신할 때 gRPC로 요청하는 것인지 모바일 엔지니어들과 약속한 App Bridge 프로토콜로 통신하는 것인지 알 필요가 없습니다.

그리고 크롬 확장도 직접 개발하였기 때문에 모바일과 통신하는 내용도 크롬 개발자도구의 pbkit 탭에서 네트워크탭을 보듯이 편하게 확인할 수 있습니다.

protobuf 스키마 컴파일러를 직접 만들었기 때문에 코드 편집기에서 Go to Definition 같은 기능을 금방 만들 수 있겠다 싶어서 VSCode 확장도 만들었습니다.
기존에 VSCode 전용 protobuf 확장들은 문법 강조 정도의 기능만 제공이 되었는데, pbkit vscode 확장은 제대로 작동하는 Go to Definition 기능이 들어있습니다.

앞으로는 swift/kotlin/python 등 다른 언어 지원, 서버 유즈케이스 지원, 문서 생성 도구, 린팅/포매팅 도구 등을 개발할 계획을 갖고 있습니다.
이런 도구들을 같이 개발할 엔지니어도 모시고 있습니다: https://riiid.com/ko/career/dx-software-engineer

많은 관심 부탁드립니다.

pbkit 저장소: https://github.com/pbkit/pbkit
vscode 확장: https://marketplace.visualstudio.com/items?itemName=pbkit.vscode-pbkit
크롬 확장: https://chrome.google.com/webstore/detail/…

저희 회사에서는 몇년전에 gRPC와 저울질하다가 Thrift를 선택했었습니다. Thrift도 JS 제너레이터가 불완전해서 자체적으로 수정했는데 못 할짓임을 깨달았습니다. 그래서 gRPC를 선택했어야 하나 싶었는데 그쪽도 사정이 썩 좋진 않나 보네요.

저희는 이후 GraphQL을 선택했고 저는 만족하고 있습니다. 가끔 통신 오버헤드가 걱정되긴 하지만 바이너리 기반의 프로토콜은 못 쓰겠더라고요

당근마켓에서 잘 쓰고 있습니다!! ( _ _ )

내부 API 매시용으로 잘 써먹어보려고 노력하고 있습니다 ㅎㅎ

오오 대단하십니다!

그나저나 회사에서 이미 프로덕션으로 쓸 정도면 v0.0.44 같이 pre-alpha 스러운 버전은 그만 쓰셔도 될 거 같아요.

버전 숫자만 보고 쓰지 않을 분들이 계실거 같네요 ㅠ

우와 컴파일러를 직접 만드셨군요. 멋집니다! (golang 코드가 어떻게 생성되나 궁금했는데 현재는 deno랑 node.js만 지원하나보네요) 저는 protoc나 buf에 ts-proto 등을 붙여쓰곤하는데 ts-proto랑은 생성되는 ts 코드 차이가 어떻게 되는지 궁금하네요.

뭔가 돌아서 가는 기분인듯영 https://github.com/trpc/trpc

bichi 님 / 서버 API gRPC protocol로 제공될 경우, trcp는 이를 지원하기 위한건 아니지 않을까요~?

gRPC/Protobuf 스택을 쓰는게 이상적이지 않다는데에는 동의해요. (제가 원해서 쓴게 아니고 회사 사정상 쓴 거라)
다만 trpc는 zod를 이용해서 인터페이스를 정의하기 때문에 모든 플랫폼에서 타입스크립트를 사용할 때에 이상적일 듯 합니다.
서버를 kotlin으로 작성하는 저희 환경에서 사용하기는 어려울 것 같고, 모바일 네이티브(swift, kotlin)와 통신하는 경우에도 적합해보이지 않습니다.

gRPC 관련 글은 언제나 환영입니다 :)

우와 코드에 VS/크롬 확장까지.. 멋지네요!! 응원합니다.
소개글을 엄청 잘 적어주셔서 그냥 Repo 방문한 사람보다, 긱뉴스 통해서 방문하신 분들이 더 많은 정보를 얻어가게 될 듯 ^^;

현재 Protobuf 사용중이신 분들이 댓글 남겨주시면 도움 많이 될 것 같아요.