๐Ÿ”ฎ

gRPC with BSR

๋ถ„๋ฅ˜
Dev Log ๐Ÿ’ป
์ž‘์„ฑ์ž
1 more property

What is RPC(Remote Procedure call)?

RPC๋Š” ์œ„ํ‚คํ”ผ๋””์•„์˜ ์„ค๋ช…์„ ๋นŒ๋ฆฌ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค.
๋ณ„๋„์˜ ์›๊ฒฉ ์ œ์–ด๋ฅผ ์œ„ํ•œ ์ฝ”๋”ฉ ์—†์ด ๋‹ค๋ฅธ ์ฃผ์†Œ๊ณต๊ฐ„์—์„œ ํ•จ์ˆ˜๋‚˜ ํ”„๋กœ์‹œ์ €๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ„ ํ†ต์‹  ๊ธฐ์ˆ ์ด๋‹ค. ๋‹ค์‹œ ๋งํ•ด, ์›๊ฒฉ ํ”„๋กœ์‹œ์ € ํ˜ธ์ถœ์„ ์ด์šฉํ•˜๋ฉด ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰ ํ”„๋กœ๊ทธ๋žจ์— ๋กœ์ปฌ ์œ„์น˜์— ์žˆ๋“  ์›๊ฒฉ ์œ„์น˜์— ์žˆ๋“  ๋™์ผํ•œ ์ฝ”๋“œ๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
Plain Text
๋ณต์‚ฌ
์œ„๋Š” client๊ฐ€ server์˜ GetUser๋ผ๋Š” ์„œ๋ฒ„์˜ ๋กœ์ง์„ ํ˜ธ์ถœํ•˜๋Š” rpc ๋‹จ๊ณ„๋ฅผ ๋‚˜ํƒ€๋‚ธ ๋‹ค์ด์–ด๊ทธ๋žจ์ด๋‹ค.

What is gRPC?

gRPC๋ž€ ์œ„์—์„œ ์„ค๋ช…ํ•œ RPC ์•ž์— g๊ฐ€ ๋ถ™์—ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์ด ์ƒ๊ฐํ•˜๋Š” ๊ทธ๊ฒŒ ๋งž๋‹ค. ๋ฐ”๋กœ Google์ด๋‹ค.
google Remote Procedure call ์ด ๋ฐ”๋กœ gRPC์ด๋‹ค.
๊ตฌ๊ธ€์—์„œ ๊ฐœ๋ฐœํ•œ ์–ด๋””์—์„œ๋‚˜ ๋™์ž‘ํ•˜๋Š” ๊ณ ์„ฑ๋Šฅ RPC ํ”„๋ ˆ์ž„์›Œํฌ ์˜คํ”ˆ์†Œ์Šค์ด๋‹ค.
gRPC์—์„œ ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋‹ค๋ฅธ ์‹œ์Šคํ…œ์˜ ์„œ๋ฒ„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ local ๊ฐœ์ฒด์ธ ๊ฒƒ ์ฒ˜๋Ÿผ
์ง์ ‘ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋ถ„์‚ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ์„œ๋น„์Šค๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
๋งŽ์€ RPC ์‹œ์Šคํ…œ์—์„œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ gRPC๋Š” ์„œ๋น„์Šค๋ฅผ ์ •์˜ํ•˜๊ณ ,
๋งค๊ฐœ ๋ณ€์ˆ˜์™€ ๋ฐ˜ํ™˜ ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜์—ฌ ์›๊ฒฉ์œผ๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •ํ•˜๋Š” ์•„์ด๋””์–ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ๋‹ค.
์„œ๋ฒ„๋Š” ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  gRPC ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ ํ˜ธ์ถœ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.
ํด๋ผ์ด์–ธํŠธ๋Š” ์„œ๋ฒ„์™€ ๋™์ผํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๋Š” stub์„ ๊ฐ€์ง„๋‹ค.

Supported languages

ํ˜„์žฌ gRPC ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ์–ธ์–ด๋“ค์„ ์ง€์›ํ•˜๊ณ  ์žˆ๋‹ค.
โ€ข
โ€ข
โ€ข
โ€ข
โ€ข
โ€ข
โ€ข
โ€ข
โ€ข
โ€ข
โ€ข
โ€ข

REST vs gRPC

REST
gRPC
protocol
HTTP / 1.1
HTTP / 2
payload
JSON
ProtoBuf
API contract
Strict, required
Loose, optional
security
TLS/SSL
TLS/SSL
streaming
one way
Bidirectional
Browser support
All
gRPC-web
gRPC๊ฐ€ HTTP/2 ์™€ ํ›„์ˆ  ํ•  ProtoBuf๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋“ฑ ์—ฌ๋Ÿฌ ์ด์œ ๋กœ ์ธํ•ด REST ๋Œ€๋น„ ์ข‹์€ performance๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

What is ProtoBuf(Protocol Buffer)?

โ€ข
google์—์„œ ๊ฐœ๋ฐœํ•œ ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ Serialization ํ•˜๋Š” ๊ธฐ๋ฒ•์ด๋‹ค.
โ€ข
๋ฐ์ดํ„ฐ ์œ ํ˜•, ๋ฐ์ดํ„ฐ ํƒ€์ž… ๋“ฑ์„ 1byte๋กœ ์‹๋ณ„ํ•˜๊ณ , ์ฃผ์–ด์ง„ length ๋งŒํผ๋งŒ ์ฝ์–ด์„œ ์šฉ๋Ÿ‰์ด ์ž‘๋‹ค.

Proto File

.proto ํ™•์žฅ์ž๋ฅผ ๊ฐ–๋Š” ProtoBuf์˜ ๊ธฐ๋ณธ ์ •๋ณด๋ฅผ ๋ช…์„ธํ•˜๋Š” ํŒŒ์ผ์ด๋‹ค.

1. Message

syntax = "proto3"; // proto buf version message MessageName { string name = 1; int32 id = 2; optional bool do_you_wanna_build_snowman = 3; repeated int32 snowman_made_date = 4; }
Protobuf
๋ณต์‚ฌ
โ€ข
message ์ด๋ฆ„์€ CamelCase, field ์ด๋ฆ„์€ snake ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•˜๋Š”๊ฒƒ์„ ๊ถŒ์žฅ.
โ€ข
field ์ด๋ฆ„์„ ์ˆซ์ž๋กœ ์‹œ์ž‘ํ•  ์ˆ˜ ์—†๋‹ค. (ย 1_nameย โ†’ name_1)
โ€ข
field ๋Š” ๊ณ ์œ ํ•œ ๋ฒˆํ˜ธ๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋˜๋Š”๋ฐ, 1 ~ 536,870,911 ๊นŒ์ง€ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค(19000 ~ 19999๋Š” reversed๋œ ๊ฐ’์œผ๋กœ ์‚ฌ์šฉ๋ถˆ๊ฐ€)
โ€ข
required,ย optional,ย repeatedย ์˜ต์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
โ—ฆ
requiredย - ๋ฐ˜๋“œ์‹œ ํ•˜๋‚˜์˜ ํ•„๋“œ๋ฅผ ๊ฐ€์ ธ์•ผํ•œ๋‹ค. (proto3 ๋ถ€ํ„ฐ ์‚ฌ์šฉ x)
โ—ฆ
optionalย - ์—†๊ฑฐ๋‚˜ ํ•˜๋‚˜๋งŒ ๊ฐ€์ ธ์•ผ ํ•˜๋Š” ํ•„๋“œ.
โ—ฆ
repeatedย - ๋ฐ˜๋ณต์ ์œผ๋กœ ์—ฌ๋Ÿฌ๋ฒˆ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค. ์ˆœ์„œ๋Š” ๋ณด์กด๋œ๋‹ค.
โ—ฆ
map - key/value ํ•„๋“œ ํƒ€์ž…. Seeย Maps.
โ—ฆ
oneof - ์•„๋ž˜ proto์™€ ๊ฐ™์ด ์ •์˜ํ•˜๋ฉด. ์•„๋ž˜ go ์ฝ”๋“œ ์˜ˆ์‹œ์ฒ˜๋Ÿผ generate ๋œ๋‹ค. (๋‹น์—ฐํ•˜์ง€๋งŒ ์–ธ์–ด๋งˆ๋‹ค ์ƒ์„ฑ๋˜๋Š” ์ฝ”๋“œ๋Š” ๋‹ค๋ฅด๋‹ค.)
package account; message Profile { ย  oneof avatar { ย  ย  string image_url = 1; ย  ย  bytes image_data = 2; ย  } }
Protobuf
๋ณต์‚ฌ
type Profile struct { // Types that are valid to be assigned to Avatar: // *Profile_ImageUrl // *Profile_ImageData Avatar isProfile_Avatar `protobuf_oneof:"avatar"` } type Profile_ImageUrl struct { ImageUrl string } type Profile_ImageData struct { ImageData []byte }
Go
๋ณต์‚ฌ

2. Package

package seoul.company; message TestBank { // ... } message Resume { seoul.company.Testbank testbank_1 = 1; // possible Testbank testbank_2 = 2 // possible }
Protobuf
๋ณต์‚ฌ
โ€ข
pakage๋Š” message ํƒ€์ž… ์ด๋ฆ„์„ ์ค‘์ฒฉ์—†์ด ๊ตฌ๋ถ„ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

3. Service

service HelloWorld { rpc Hello (HelloRequest) returns (HelloResponse) {}; rpc HelloClientStream (stream HelloClientStreamRequest) returns (HelloClientStreamResponse) {}; rpc HelloServerStream (HelloServerStreamRequest) returns (stream HelloServerStreamResponse) {}; rpc HelloBiStream (stream HelloBiStreamRequest) returns (stream HelloBiStreamResponse) {}; }
Protobuf
๋ณต์‚ฌ
โ€ข
RPC๋ฅผ ํ†ตํ•ด Server๊ฐ€ Client์—๊ฒŒ ์ œ๊ณตํ•  ํ•จ์ˆ˜์˜ ํ˜•ํƒœ๋ฅผ ์ •์˜ํ•œ๋‹ค.
โ€ข
CamelCase๋ฅผ ๊ถŒ์žฅํ•œ๋‹ค.
โ€ข
๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹จ์ผ ์š”์ฒญ/์‘๋‹ต์œผ๋กœ ๋™์ž‘ํ•˜์ง€๋งŒ,ย streamย ์˜ต์…˜์„ ์‚ฌ์šฉํ•ด์„œ RPC๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

What is BSR?

BSR(Buf Schema Registry) ์€ Protobuf ํŒŒ์ผ๋“ค์„ ๋ฒ„์ „๋œ ๋ชจ๋“ˆ๋กœ ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ์ €์žฅ์†Œ์ด๋‹ค.
ํ•ด๋‹น ์ €์žฅ์†Œ๋ฅผ ์ด์šฉํ•˜๋ฉด ๊ฐœ์ธ์ด๋‚˜ ๊ธฐ๊ด€์ด API๋“ค์„ ๋งˆ์ฐฐ์—†์ด ์‚ฌ์šฉํ•˜๊ณ  ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋‹ค.
BSR์€ ํƒ์ƒ‰๊ฐ€๋Šฅํ•œ UI์™€ ์˜์กด์„ฑ ๊ด€๋ฆฌ, API ๊ฒ€์ฆ๊ณผ ๋ฒ„์ €๋‹, ๋ฌธ์„œ ์ƒ์„ฑ ๊ทธ๋ฆฌ๊ณ  ์›๊ฒฉ ์ฝ”๋“œ ์ œ๋„ˆํ…Œ์ดํ„ฐ๋ฅผ ํ†ตํ•ด ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ ์‹œ์Šคํ…œ์„ ์ œ๊ณตํ•œ๋‹ค.
22/09/26 ์ผ ๊ธฐ์ค€ ๋ฒ ํƒ€ ๋ฒ„์ „์œผ๋กœ ๋ฌด๋ฃŒ์ด๋‚˜ ๋ฒ ํƒ€๋ฒ„์ „ ์ดํ›„์— team์œผ๋กœ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์œ ๋ฃŒ(10๋‹ฌ๋Ÿฌ)๋กœ ์ „ํ™˜ ๋  ์˜ˆ์ •์ด๋‹ค.
gRPC, protoBuf ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ํ•ด๋‹น ์„œ๋น„์Šค๋ฅผ ๋ฐ˜๋“œ์‹œ ์ด์šฉํ•  ํ•„์š”๋Š” ์—†๋‹ค.

Install

$ brew install bufbuild/buf/buf
Bash
๋ณต์‚ฌ

Login

$ buf registry login UserName: <USERNAME> Token: <TOKEN>
Shell
๋ณต์‚ฌ
์œ„ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•˜๊ณ , ์œ ์ €๋„ค์ž„, ํ† ํฐ์„ ์ž…๋ ฅํ•˜๋ฉด ๋กœ๊ทธ์ธ ๋œ๋‹ค.
์ •์ƒ์ ์œผ๋กœ ๋กœ๊ทธ์ธ์ด ์™„๋ฃŒ๋˜๋ฉด ~/.netrc ํŒŒ์ผ์— ์•„๋ž˜์™€ ๊ฐ™์ด ์ €์žฅ๋œ๋‹ค.
machine buf.build login <USERNAME> password <TOKEN> machine go.buf.build login <USERNAME> password <TOKEN>
Shell
๋ณต์‚ฌ
๋กœ๊ทธ์ธ์ด ์™„๋ฃŒ๋˜๋ฉด BSR์˜ ์ ‘๊ทผ ๊ถŒํ•œ ์„ค์ •์ด ๋๋‚ฌ๋‹ค.
์ด์ œ repository๋ฅผ ์ƒ์„ฑํ•˜๊ณ  module์„ push ํ•  ์ˆ˜ ์žˆ๋‹ค.

How to use

์‹œ์ž‘ํ•˜๊ธฐ ์•ž์„œ์„œ ๊ธฐ๋ณธ์ ์ธ ์šฉ์–ด๋“ค์„ ํ™•์ธํ•ด๋ณด์ž.
โ€ข
Modules
Modules ์€ Buf์™€ BSR์˜ ํ•ต์‹ฌ์ด๋‹ค. module ์€ ๊ตฌ์„ฑ๋˜๊ณ , ๋นŒ๋“œ๋˜๊ณ , ๋ฒ„์ „์ด ๋ช…์‹œ๋œ ๋…ผ๋ฆฌ๋‹จ์œ„์˜ Protobuf์˜ ์ง‘ํ•ฉ์ด๋‹ค. module์€ buf.yaml ์„ ์ดˆ๊ธฐํ™”ํ•  ๋•Œ ์ƒ์„ฑํ•œ๋‹ค.
โ€ข
Repositories
module๋Š” repository ์— ์ €์žฅ๋œ๋‹ค. ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋Š” ๋ชจ๋“ˆ์˜ ๋ชจ๋“  ๋ฒ„์ „์„ ์ €์žฅํ•œ๋‹ค. ๊ฐ ๋ฒ„์ „์€ ์ปค๋ฐ‹์ด๋‚˜ ์„ ํƒ์ ์œผ๋กœ ํƒœ๊ทธ์— ์˜ํ•ด์„œ ์‹๋ณ„๋œ๋‹ค.
Git ์ €์žฅ์†Œ์™€ ๋Œ€๋žต ๋น„์Šทํ•˜์ง€๋งŒ BSR ์ €์žฅ์†Œ๋Š” ์›๊ฒฉ ์œ„์น˜์ผ ๋ฟ์ด๋ฉฐ ์ €์žฅ์†Œ "ํด๋ก "์ด๋ผ๋Š” ๊ฐœ๋…์€ ์—†๋‹ค. ์ฆ‰, ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋Š” ์—ฌ๋Ÿฌ ์œ„์น˜์— ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค.
โ€ข
Module names
module์€ ์ด๋ฆ„๊ณผ 3๊ฐœ์˜ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ–๋Š”๋‹ค.
โ€ข
Remote: BSR์— ํ˜ธ์ŠคํŒ… ํ•˜๊ธฐ์œ„ํ•œ DNS์ด๋ฆ„์ด๋‹ค. buf.build ์™€ ๊ฐ™๋‹ค.
โ€ข
Owner: ๊ฐœ์ธ์ด๋‚˜ ๊ธฐ๊ด€๊ณผ ๊ฐ™์€ repo์˜ ์ฃผ์ธ์ด๋‹ค.
โ€ข
Repository: repo์˜ ์ด๋ฆ„์ด๋‹ค.
์˜ˆ์‹œ,
Name
Remote
Owner
Repository
buf.build/testbank/tools
buf.build
testbank
tools
buf.build/korea/weather
buf.build
korea
weather
solvetheproblem.io/solve/solve
solvetheproblem.io
solve
solve

Create Repository

command line ์—์„œ ๋ ˆํฌ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ buf.build ์ฝ˜์†”์—์„œ Create repository ๋ฅผ ํด๋ฆญํ•ด์„œ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.
โ€ข
command line
buf beta registry repository create buf.build/$BUF_USER/$REPO_NAME --visibility public
Shell
๋ณต์‚ฌ
โ€ข
buf.build console (home โ†’ ์šฐ์ธก ์ƒ๋‹จ name ํด๋ฆญ โ†’ Repositories โ†’ Create repository)

Configure

bufย ๋Š” buf.yamlย ๊ณผ ํ•จ๊ป˜ ๊ตฌ์„ฑ๋œ๋‹ค. ์•„๋ž˜ ์ปค๋งจ๋“œ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
$ buf mod init
Bash
๋ณต์‚ฌ

Set name

buf.yaml ํŒŒ์ผ์—์„œ name์„ ๋งค์นญํ•ด ์ฃผ๋ฉด ๋œ๋‹ค.
version: v1 name: <Remote>/<Owner>/<Repository> lint: use: - DEFAULT breaking: use: - FILE
YAML
๋ณต์‚ฌ

Push the module

buf.yaml ์ด ์žˆ๋Š” ํด๋”์—์„œ ์•„๋ž˜ ์ปค๋งจ๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด ๋œ๋‹ค.
$ buf push
Shell
๋ณต์‚ฌ
ํ•ด๋‹น ์ปค๋งจ๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด Buf Registry์— code๊ฐ€ push ๋œ๋‹ค.

Write Configuration

โ€ข
buf.yaml
buf.yaml ํŒŒ์ผ์€ ๋ชจ๋“ˆ์„ ์ •์˜ํ•˜๊ณ  Protobuf ํŒŒ์ผ์˜ ๋ฃจํŠธ์— ์œ„์น˜ํ•œ๋‹ค.
buf.yaml ์˜ ๊ตฌ์„ฑ์€ buf์—๊ฒŒ .proto ํŒŒ์ผ์€ ์–ด๋””์— ์žˆ๊ณ  lint, breaking ๋“ฑ ์˜ต์…˜์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
buf.lock
buf mod update ์ปค๋ฉ˜๋“œ๋ฅผ ํ†ตํ•ด ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” ๋ถ€๋ถ„์ด๋‹ˆ ์ˆ˜์ •ํ•˜์ง€ ๋ง์ž.
buf.gen.yaml
buf.gen.yaml ํŒŒ์ผ์€ buf generate ์ปค๋งจ๋“œ๊ฐ€ protoc ํ”Œ๋Ÿฌ๊ทธ์ธ๋“ค์„ ์–ด๋–ค์‹์œผ๋กœ ์‹คํ–‰ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ํ†ต์ œ์ด๋‹ค.
version: v1 plugins: - name: cpp out: gen/proto/cpp - name: java out: gen/proto/java - name: go out: gen/proto/go opt: paths=source_relative - name: go-grpc out: gen/proto/go opt: - paths=source_relative - require_unimplemented_servers=false
YAML
๋ณต์‚ฌ
buf.work.yaml
buf.work.yaml์€ workspace๋ฅผ ์ •์˜ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ํ•˜๋‚˜ ์ด์ƒ์˜ ๋ชจ๋“ˆ์ด ๊ณตํ†ต๋œ ๋ฆฌํ…ํ† ๋ฆฌ์— ์กด์žฌํ•  ๋•Œ local ๋ชจ๋“ˆ์ด ๋‹ค๋ฅธ local๋ชจ๋“ˆ์„ import ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.
. โ”œโ”€โ”€ buf.work.yaml โ”œโ”€โ”€ testbank-rpc โ”‚ โ”œโ”€โ”€ testbank โ”‚ โ”‚ โ””โ”€โ”€ contents โ”‚ โ”‚ โ””โ”€โ”€ v1 โ”‚ โ”‚ โ””โ”€โ”€ user.proto โ”‚ โ””โ”€โ”€ buf.yaml โ””โ”€โ”€ solve-rpc โ”œโ”€โ”€ solve โ”‚ โ””โ”€โ”€ solve โ”‚ โ””โ”€โ”€ v1 โ”‚ โ””โ”€โ”€ problem.proto โ””โ”€โ”€ buf.yaml
Bash
๋ณต์‚ฌ
์˜ˆ๋ฅผ ๋“ค์–ด ์œ„์™€ ๊ฐ™์€ ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๊ฐ–๊ณ  ์žˆ์„ ๋•Œ,
# buf.work.yaml version: v1 directories: - testbank-rpc - solve-rpc
Bash
๋ณต์‚ฌ
์œ„์™€ ๊ฐ™์ด buf.work.yaml์„ ์ž‘์„ฑํ•˜๋ฉด testbank-rpc์—์„œ solve-rpc, ํ˜น์€ ๊ทธ ๋ฐ˜๋Œ€, ๋ฅผ import ํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

breaking changes

version: v1 lint: use: - DEFAULT breaking: use: - FILE
YAML
๋ณต์‚ฌ
โ€ข
Option : FILE, PACKAGE, WIRE, WIRE JSON
default ๊ฐ’์€ FILE ์ด๋‹ค. API์˜ ์‚ฌ์šฉ์ž ๊ฐ„์— ์ตœ๋Œ€ํ•œ์˜ ํ˜ธํ™˜์„ฑ์„ ๋ณด์žฅํ•  ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค.
์ผ๋ฐ˜์ ์œผ๋กœ lint๊ตฌ์„ฑ์„ ์ง€์ •ํ•  ๋•Œ ์ฒ˜๋Ÿผ ํŠน์ • ๋ณ€๊ฒฝ ๊ทœ์น™์„ ํฌํ•จ/์ œ์™ธํ•˜๊ธฐ๋ณด๋‹ค๋Š” ์ด๋Ÿฌํ•œ ์˜ต์…˜ ์ค‘ ํ•˜๋‚˜๋งŒ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
// pet/v1/pet.proto message Pet { - PetType pet_type = 1; + string pet_tyep = 1; string pet_id = 2; string name = 3; }
Protobuf
๋ณต์‚ฌ
๋งŒ์•ฝ ์œ„์˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ Pet.pet_type field๋ฅผ PetType ์—์„œ string ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚˜์„œ,
buf breaking ๋ช…๋ น์–ด๋ฅผ ์ˆ˜ํ–‰ํ•ด ๋ณด๋ฉด ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„์˜ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
$ buf breaking --against "../../.git#branch=main,subdir=start/petapis" pet/v1/pet.proto:20:3:Field "1" on message "Pet" changed type from "enum" to "string".
Shell
๋ณต์‚ฌ

lint

buf lint ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด API ์ •์˜์— ๊ฐ€์žฅ ์ข‹์€ ์‚ฌ๋ก€๋ฅผ ๊ฒฐ์ •ํ•˜๊ฒŒ ํ•ด์„œ ์ผ๊ด€์„ฑ์„ ๊ฐ•์ œํ•˜๊ณ  ์ง€์ผœ์ค€๋‹ค.
$ buf lint --error-format=json {"path":"google/type/datetime.proto","start_line":17,"start_column":1,"end_line":17,"end_column":21,"type":"PACKAGE_VERSION_SUFFIX","message":"Package name \"google.type\" should be suffixed with a correctly formed version, such as \"google.type.v1\"."} {"path":"pet/v1/pet.proto","start_line":44,"start_column":10,"end_line":44,"end_column":15,"type":"FIELD_LOWER_SNAKE_CASE","message":"Field name \"petID\" should be lower_snake_case, such as \"pet_id\"."} {"path":"pet/v1/pet.proto","start_line":49,"start_column":9,"end_line":49,"end_column":17,"type":"SERVICE_SUFFIX","message":"Service name \"PetStore\" should be suffixed with \"Service\"."}
Shell
๋ณต์‚ฌ
buf.yaml ํŒŒ์ผ์—์„œ ignore ์˜ต์…˜์œผ๋กœ ํŠน์ • ํŒŒ์ผ์„ lint์—์„œ ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.
version: v1 lint: use: - DEFAULT ignore: - google/type/datetime.proto breaking: use: - FILE
YAML
๋ณต์‚ฌ

Using module

์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ ์–ธ์–ด์—์„œ ์›ํ•˜๋Š” ํ…œํ”Œ๋ฆฟ์œผ๋กœ push๋œ ๋ชจ๋“ˆ์„ ๋ชจ๋“ˆ์„ ๋ฐ›์•„์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
โ€ข
go
$ go get go.buf.build/${template_owner}/${template_name}/${owner}/${repository}
Bash
๋ณต์‚ฌ
โ€ข
js
$ npm config set @buf:registry https://npm.buf.build $ npm install @buf/${template_owner}_${template_name}_${owner}_${repository}
Bash
๋ณต์‚ฌ
ํ˜น์€, buf.gen.yaml ํŒŒ์ผ์„ ์ž‘์„ฑํ–ˆ๋‹ค๋ฉด buf generate ๋ฅผ ํ†ตํ•ด์„œ ๋กœ์ปฌ์—์„œ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
$ buf generate
Bash
๋ณต์‚ฌ
์œ„ ์ปค๋งจ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด buf.gen.yaml ์˜ out์œผ๋กœ ์ง€์ •ํ•œ ํด๋”์— ์ƒ์„ฑ๋œ๋‹ค.

End

ํ˜„์žฌ ํ…Œ์ŠคํŠธ๋ฑ…ํฌ๋Š” ํ†ต์‹ ์—์„œ gRPC๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ํ•ด๋‹น ProtoBuf๋ฅผ BSR์„ ์‚ฌ์šฉํ•ด์„œ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๋‹ค.
gRPC๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ž‘์„ฑํ•˜๋Š” ProtoBuf์— ๋”ฐ๋ฅธ ํฐ ์ด์ ์ด ์žˆ๋‹ค.
1. ProtoBuf๋ฅผ ์ด์šฉํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ์–ธ์–ด์— ๋งž๋Š” ์ฝ”๋“œ๋ฅผ generateํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
2. ProtoBuf ์ž์ฒด๋กœ API๋ช…์„ธ์„œ ๊ธฐ๋Šฅ์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋”ฐ๋กœ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
์ฒ˜์Œ ๊ธฐ๋Šฅ์„ ์„ค๊ณ„ํ•  ๋•Œ ProtoBuf ์ž‘์„ฑ์— ์‹ ๊ฒฝ์„ ๋งŽ์ด ์“ฐ๋ฉด ์ดํ›„์— ๊ฐœ๋ฐœ์ด ํŽธํ•ด์ง„๋‹ค.
BSR์˜ ์‚ฌ์šฉ์€ ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๊ฒƒ ์ฒ˜๋Ÿผ ํ•„์ˆ˜๊ฐ€ ์•„๋‹ˆ์ง€๋งŒ, ํ•ด๋‹น ์ €์žฅ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด commit๊ณผ tag ๋“ฑ์œผ๋กœ ProtoBuf๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์ˆ˜์›”ํ•˜๊ณ  module์„ ์‰ฝ๊ฒŒ ๋‚ด๋ ค๋ฐ›์•„์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
์ด์ง€ํ›ˆ Software Engineer
์„ธ์ƒ ๋ชจ๋“ ๊ฒƒ์— ๊ด€์‹ฌ์ด ๋งŽ๊ณ , ์„ธ์ƒ์„ ํ–ฅํ•œ ๊ด€์‹ฌ์œผ๋กœ ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Reference