[gRPC] gRPC๋ฅผ ํ™œ์šฉํ•œ MSA ๊ฐ„ ํ†ต์‹ , Spring Boot์—์„œ gRPC๋กœ ํ†ต์‹ ํ•˜๊ธฐ (feat. ์„ฑ๋Šฅ ์ธก์ •)

1. gRPC๋ž€?

gRPC๋ฅผ ์•Œ์•„๋ณด๊ธฐ ์•ž์„œ RPC๋ž€ Remote Procedure Call์˜ ์•ฝ์ž๋กœ ๋‹ค๋ฅธ ์ปดํ“จํ„ฐ์— ์žˆ๋Š” ์–ด๋–ค ๊ธฐ๋Šฅ์„ ์ž๊ธฐ ๊ธฐ๋Šฅ์ธ ๊ฒƒ ์ฒ˜๋Ÿผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋กœํ† ์ฝœ์ด๋‹ค.

RPC๋Š” ์–ธ์–ด ๋…๋ฆฝ์ ์ด๋ฏ€๋กœ ์„œ๋กœ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด์—์„œ๋„ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค.

๊ฐœ๋ฐœ์ž๋Š” ์„œ๋ฒ„๋‚˜ ํ†ต์‹  ๊ณผ์ •์— ๋Œ€ํ•ด ํ•˜๋‚˜ํ•˜๋‚˜ ์•Œ์•„๋‘๊ฑฐ๋‚˜ ๊ณ ๋ คํ•  ํ•„์š” ์—†์ด ๋งˆ์น˜ ๋กœ์ปฌ ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ ธ๋‹ค ์“ฐ๋“ฏ ๊ธฐ๋Šฅ๋“ค์„ ํ•„์š”์— ๋”ฐ๋ผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

 

gRPC๋Š” ๊ตฌ๊ธ€์—์„œ ๊ฐœ๋ฐœํ•œ ์˜คํ”ˆ์†Œ์Šค ๊ธฐ์ˆ ๋กœ ๋‹ค์–‘ํ•œ ํ”Œ๋žซํผ์—์„œ ์„œ๋กœ ๋‹ค๋ฅธ ์–ธ์–ด๋กœ ์ž‘์„ฑ๋œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐ„ ํ†ต์‹ ์„ ์œ„ํ•œ ํšจ์œจ์ ์ด๊ณ  ๊ฐ„ํŽธํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค. gRPC๋Š” ์ด์ „์˜ RPC ์‹œ์Šคํ…œ๊ณผ ๋‹ฌ๋ฆฌ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ „์†ก ๋ฐ ๋ฉ€ํ‹ฐํ”Œ๋žซํผ ์ง€์› ๋“ฑ์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. ํ˜„์žฌ๊นŒ์ง€๋„ ์ง€์†์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ์™€ ๊ฐœ์„ ์ด ์ด๋ฃจ์–ด์ง€๋ฉฐ, ํด๋ผ์šฐ๋“œ ๋„ค์ดํ‹ฐ๋ธŒ ์•„ํ‚คํ…์ฒ˜์™€์˜ ํ˜ธํ™˜์„ฑ๋„ ๊ฐ•ํ™”๋˜๊ณ  ์žˆ๋‹ค.

 

 

 

 

 

 

 

 

 

 

 

2. gRPC ๋“ฑ์žฅ ๋ฐฐ๊ฒฝ

gRPC ์ด์ „์—” RPC, Rest API ํ†ต์‹ ์ด ์กด์žฌํ–ˆ๋‹ค.

 

RPC

RPC๋Š” IDL์„ ์‚ฌ์šฉํ•˜์—ฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ช…์‹œํ•œ๋‹ค. IDL์ด๋ž€ Interface Definition Language ์•ฝ์ž๋กœ ์†Œํ”„ํŠธ์›จ์–ด ์ปดํฌ๋„ŒํŠธ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฌ˜์‚ฌํ•˜๊ธฐ ์œ„ํ•œ ๋ช…์„ธ ์–ธ์–ด์ด๋‹ค. 

 

์–ด๋Š ํ•œ ์–ธ์–ด์— ๊ตญํ•œ๋˜์ง€ ์•Š๋Š” ์–ธ์–ด ์ค‘๋ฆฝ์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฌ˜์‚ฌํ•จ์œผ๋กœ์จ, ๊ฐ™์€ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์†Œํ”„ํŠธ์›จ์–ด ์ปดํฌ๋„ŒํŠธ ์‚ฌ์ด์˜ ํ†ต์‹ ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•œ๋‹ค.

 

RPC์˜ ๋™์ž‘ ํ๋ฆ„์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

  1. IDL์„ ํ†ตํ•ด ํ˜ธ์ถœ์— ๋Œ€ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜
  2. ์ •์˜๋œ IDL์„ ๊ธฐ๋ฐ˜์œผ๋กœ rpcgen์ด๋ผ๋Š” rpc ํ”„๋กœํ† ์ฝœ ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ํ†ตํ•ด ์ฝ”๋“œ(stub)๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค. stub์„ ํ†ตํ•ด Client๋Š” procedure ํ˜ธ์ถœ์„ ์œ„ํ•œ ์ฐธ์กฐ์ž๊ฐ€ ์ƒ๊ฒผ๊ณ , Server๋Š” procedure ์ดํ•ด๋ฅผ ์œ„ํ•œ ์ฐธ์กฐ๊ฐ€ ์ƒ๊ธฐ๊ฒŒ ๋จ.
  3. Client๋Š” ์ž์‹ ์˜ ํ”„๋กœ๊ทธ๋žจ์—์„œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ stub์— ์ •์˜๋œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉ.
  4. Client์—์„œ Stub์— ์ •์˜๋œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ Client stub์€ RPC ๋Ÿฐํƒ€์ž„์„ ํ†ตํ•ด ํ•จ์ˆ˜ ํ˜ธ์ถœ.
  5. Server๋Š” ์ˆ˜์‹ ๋œ procedure ํ˜ธ์ถœ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ ํ›„ ๊ฒฐ๊ณผ ๊ฐ’ ๋ฐ˜ํ™˜.
  6. ์ตœ์ข…์ ์œผ๋กœ Client ํ”„๋กœ๊ทธ๋žจ์€ ์„œ๋ฒ„์˜ ๊ฒฐ๊ณผ ๊ฐ’์„ ๋ฐ˜ํ™˜ ๋ฐ›์Œ.

 

RPC๋ฅผ ํ†ตํ•ด ํ•˜๋ถ€ ๋„คํŠธ์›Œํฌ ํ”„๋กœํ† ์ฝœ์— ๋Œ€ํ•ด ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์•„๋„ ๋˜๊ณ , ํ”„๋กœ๊ทธ๋žจ ๊ฐœ๋ฐœ์—๋งŒ ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ ๋‹จ์ ๋„ ์กด์žฌํ–ˆ๋‹ค.

 

RPC ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์šธ ๋ฟ๋”๋Ÿฌ ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ๋””๋ฒ„๊น…์ด ์–ด๋ ค์šด ๋‹จ์ ์ด ์กด์žฌํ•œ๋‹ค.

์ด๋กœ ์ธํ•ด ๋ฐ์ดํ„ฐ ํ†ต์‹ ์„ Web์„ ํ™œ์šฉํ•ด ํ•ด๋ณด๋ ค ํ–ˆ๊ณ  ํƒ„์ƒํ•œ ๊ฒƒ์ด REST API ์ด๋‹ค. 

 

 

 

REST

REST(REpresentational State Transfer)๋Š” HTTP1.1 ๊ธฐ๋ฐ˜ URI๋ฅผ ํ†ตํ•ด ์ž์›์„ ๋ช…์‹œํ•˜๊ณ , HTTP Method(POST, GET, PUT, DELETE)๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ์ž์›์— ๋Œ€ํ•œ CRUD๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. 

 

REST๋Š” HTTP ํ”„๋กœํ† ์ฝœ์˜ ์ธํ”„๋ผ๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณ„๋„์˜ ์ธํ”„๋ผ๋ฅผ ๊ตฌ์ถ•ํ•  ํ•„์š”๋„ ์—†๊ณ , REST API ๋ฉ”์‹œ์ง€๊ฐ€ ์˜๋„ํ•˜๋Š” ๋ฐ”๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ๋‚˜ํƒ€๋‚ด๊ธฐ ๋•Œ๋ฌธ์— ์‰ฝ๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

 

ํ•˜์ง€๋งŒ, REST๋Š” ํ‘œ์ค€ ์ž์ฒด๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์•„ ์ •์˜๊ฐ€ ํ•„์š”ํ•˜๊ณ , ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์†Œ๋“œ๋„ 4๊ฐ€์ง€ ๋ฐ–์— ์—†์—ˆ๋‹ค.

 

REST๊ฐ€ ๋ณดํŽธ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋˜ ์ค‘์—, 2016๋…„ ๊ตฌ๊ธ€์—์„œ ๊ฐœ๋ฐœํ•œ ์˜คํ”ˆ์†Œ์Šค RPC ํ”„๋ ˆ์ž„์›Œํฌ์ธ gRPC๊ฐ€ ๋“ฑ์žฅํ•œ๋‹ค. 

 

 

 

 

gRPC

google์€ 1์ฃผ์ผ ๋™์•ˆ ๋„์šฐ๋Š” ์ผ์ฃผ์ผ ๋™์•ˆ ๋„์šฐ๋Š” ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์•ฝ 20์–ต๊ฐœ, 1์ดˆ ๋™์•ˆ ๋˜์ง€๋Š” ์›๊ฒฉ ํ˜ธ์ถœ์˜ ์ˆ˜๋Š” 100์–ต ๋ฒˆ์ด๋ผ๊ณ  ํ•œ๋‹ค. ๊ตฌ๊ธ€์€ ์ด๋Ÿฌํ•œ ๋Œ€๊ทœ๋ชจ ์„œ๋น„์Šค๋ฅผ ์šด์˜ํ•˜๊ธฐ ์œ„ํ•ด gRPC๋ฅผ ๊ฐœ๋ฐœํ–ˆ๋‹ค.

 

gPRC๋Š” IDL๋กœ PB(Protocol Buffer)๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. 

 

 

 

 

 

 

 

 

 

 

 

3. gRPC์˜ ์žฅ์ 

gRPC๋Š” HTTP/1.1 ์ด ์•„๋‹Œ HTTP/2 ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค. ๋‘ ๊ฐ€์ง€ ์ฐจ์ด์ ์€ ๋ญ˜๊นŒ??

 

HTTP/1.1 vs HTTP/2

HTTP1.1์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•œ Connection์— ํ•˜๋‚˜์˜ ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋™์‹œ ์ „์†ก, ๋‹ค์ˆ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ์ฒ˜๋ฆฌํ•˜๊ธฐ์—” ์„ฑ๋Šฅ ์ด์Šˆ๊ฐ€ ์žˆ๋‹ค. 

๋˜ํ•œ ๋ฌด๊ฑฐ์šด Header๊ฐ€ ์š”์ฒญ ๋งˆ๋‹ค ์ค‘๋ณต ์ „๋‹ฌ๋˜์–ด ๋น„ํšจ์œจ ์ ์ด์—ˆ๋‹ค. 

 

HTTP/2๋Š” ์„ฑ๋Šฅ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์†๋„ ๋ฉด์—์„œ๋„ ์šฐ์ˆ˜ํ•œ๋ฐ ํ•œ Connection์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ๊ณ , ๋ฌด๊ฑฐ์› ๋˜ Header๋ฅผ ์••์ถ•ํ•˜์—ฌ ์ค‘๋ณต์„ ์ œ๊ฑฐํ•˜๊ณ  ์ „๋‹ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— HTTP/1.1์— ๋น„ํ•ด์„œ ํ›จ์”ฌ ํšจ์œจ์ ์ด์—ˆ๋‹ค. 

 

 

๋˜ํ•œ ๋ฐ˜๋“œ์‹œ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์ด ๋“ค์–ด์™€์•ผ ์‘๋‹ต์„ ํ•  ์ˆ˜ ์žˆ๋Š” HTTP/1.1๊ณผ ๋‹ฌ๋ฆฌ, ์š”์ฒญ ์—†์ด๋„ ์„œ๋ฒ„๊ฐ€ ๋ฆฌ์†Œ์Šค๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ตœ์†Œํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

 

 

 

 

 

 

4. Protobuf ๋ž€?

์œ„์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด gRPC๋Š” IDL๋กœ PB(Protocol Buffer)๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ํ”„๋กœํ† ์ฝœ ๋ฒ„ํผ๋Š” ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ง๋ ฌํ™” ํ•˜๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค.

์—ฌ๊ธฐ์„œ ์ง๋ ฌํ™”๋ž€ Java ์‹œ์Šคํ…œ ๋‚ด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ Java ์‹œ์Šคํ…œ ์™ธ์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก Byte ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๋Š” ๊ธฐ์ˆ ์ด๋‹ค. 

 

 

Protocol Buffer๋Š” RPC์˜ IDL๊ณผ ๋™์ผํ•˜๊ฒŒ ์ค‘๋ฆฝ์ ์ธ ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด์„œ proto File์— ์ •์˜ํ•œ๋‹ค. ์ •์˜ํ•œ Proto File์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ฐ ์–ธ์–ด์— ๋งž๊ฒŒ ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค๋กœ ์ƒ์„ฑํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— protoc ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. (RPC์—์„  rpcgen)

 

protoc ์ปดํŒŒ์ผ๋Ÿฌ๋กœ Profo File์„ ์ปดํŒŒ์ผํ•˜๋ฉด ๊ฐ ์–ธ์–ด์— ๋งž๊ฒŒ ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 

 

 

Proto File ์ •์˜ => protoc ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์ด์šฉํ•˜์—ฌ ์ปดํŒŒ์ผ => ์›ํ•˜๋Š” ์†Œ์Šค ํŒŒ์ผ ์ƒ์„ฑ

 

 

 

 

 

 

 

 

 

 

 

 

5. Spring Boot ์—์„œ gRPC ์‚ฌ์šฉํ•˜๊ธฐ

gRPC - Client

- build.gradle

// grpc
buildscript {
    ext {
        protobufVersion = '3.25.1'
        protobufPluginVersion = '0.8.14'
        grpcVersion = '1.58.1'
    }
}

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.3.5'
    id 'io.spring.dependency-management' version '1.1.6'

    // grpc
    id 'com.google.protobuf' version '0.9.4'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

    // swagger
    implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'

    // grpc
    implementation "com.google.protobuf:protobuf-java-util:3.25.1"
    implementation 'com.google.protobuf:protobuf-java:3.25.1'
    implementation 'net.devh:grpc-client-spring-boot-starter:2.15.0.RELEASE' // ํด๋ผ์ด์–ธํŠธ ์˜์กด์„ฑ ์ถ”๊ฐ€
    runtimeOnly "io.grpc:grpc-netty-shaded:${grpcVersion}"
    implementation "io.grpc:grpc-protobuf:${grpcVersion}"
    implementation "io.grpc:grpc-stub:${grpcVersion}"
    compileOnly 'org.apache.tomcat:annotations-api:6.0.53'

    implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
}

// grpc
protobuf {
    protoc {
        artifact = "com.google.protobuf:protoc:${protobufVersion}"
    }
    clean {
        delete generatedFilesBaseDir
    }
    plugins {
        grpc {
            artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
        }
    }
    generateProtoTasks {
        all()*.plugins {
            grpc{}
        }
    }
}

ext {
    set('springCloudVersion', "2023.0.2")
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

tasks.named('test') {
    useJUnitPlatform()
}

 

 

 

Proto file์„ ์ •์˜ํ•ด์ค€๋‹ค. ์ด ํŒŒ์ผ์€ server์™€ client ๋ชจ๋‘ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค. ํ™•์žฅ์ž ๋ช…์€ .proto ์ด๋‹ค. 

๐Ÿ“ฆsrc
 โ”ฃ ๐Ÿ“‚main
 โ”ƒ โ”ฃ ๐Ÿ“‚java
 โ”ƒ โ”ƒ โ”— ๐Ÿ“‚com
 โ”ƒ โ”ƒ โ”ƒ โ”— ๐Ÿ“‚example
 โ”ƒ โ”ƒ โ”ƒ โ”ƒ โ”— ๐Ÿ“‚grpcclient
 โ”ƒ โ”ฃ ๐Ÿ“‚proto
 โ”ƒ โ”ƒ โ”— ๐Ÿ“œtest.proto
 โ”ƒ โ”— ๐Ÿ“‚resources
 โ”ƒ โ”ƒ โ”— ๐Ÿ“œapplication.yml

 

 

- proto ํŒŒ์ผ

syntax = "proto3";

option java_multiple_files = true;
option java_outer_classname = "SampleProto";
option java_package = "com.example.grpc.proto";

package com.example.grpc;

// req ๋ฉ”์‹œ์ง€ ์ •์˜
message SampleRequest {
  string userId = 1;   // userId ํ•„๋“œ์˜ ์‹๋ณ„์ž: 1
  string message = 2;  // messagee ํ•„๋“œ์˜ ์‹๋ณ„์ž: 2
}

// res ๋ฉ”์‹œ์ง€ ์ •์˜
message SampleResponse {
  string message = 1;
}

// ์„œ๋น„์Šค ์ •์˜
service SampleService {
  rpc SampleCall (SampleRequest) returns (SampleResponse) {}
}

 

 

- application.yml (client)

grpc:
  client:
    local-grpc-server: # ํด๋ผ์ด์–ธํŠธ ์ด๋ฆ„
      address: "static://localhost:9090" # ์„œ๋ฒ„ ์ฃผ์†Œ (๋กœ์ปฌ)
      negotiationType: "plaintext"
server:
  port: 8082

 

 

 

 

gRPC - Server

- build.gradle

client์™€ ๋™์ผํ•˜์ง€๋งŒ ์•„๋ž˜ ๋ถ€๋ถ„๋งŒ ๋ณ€๊ฒฝ

implementation 'net.devh:grpc-client-spring-boot-starter:2.15.0.RELEASE' // ํด๋ผ์ด์–ธํŠธ ์˜์กด์„ฑ ์ถ”๊ฐ€

=> 

implementation 'net.devh:grpc-server-spring-boot-starter:2.15.0.RELEASE' // ์„œ๋ฒ„ ์˜์กด์„ฑ ์ถ”๊ฐ€

 

 

 

- proto ํŒŒ์ผ

client ์™€ ๋˜‘๊ฐ™์€ ํŒŒ์ผ ์ž‘์„ฑ

 

 

- application.yml (server)

grpc:
  server:
    port: 9090 # gRPC ์„œ๋ฒ„ ํฌํŠธ
server:
  port: 8081

 

 

 

 

 

์ƒ์„ฑ ํ›„ build ํ•ด์ฃผ๋ฉด build.generated ๋””๋ ‰ํ† ๋ฆฌ ์•ˆ์— proto ํŒŒ์ผ์—์„œ ์ƒ์„ฑํ•œ service ํด๋ž˜์Šค๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค. 

 

 

 

 

- gRPC ์š”์ฒญ ์ฒ˜๋ฆฌ: SampleServiceGrpc ์˜ค๋ฒ„๋ผ์ด๋”ฉ (server)

@GrpcService
@Slf4j
public class GrpcServer extends SampleServiceGrpc.SampleServiceImplBase {

    @Override
    public void sampleCall(SampleRequest request, StreamObserver<SampleResponse> responseObserver) {
        String userId = request.getUserId();
        String message = request.getMessage();

        // ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌ
        String responseMessage = "Received message from userId: " + userId + ", message: " + message;

        log.info("[gRPC server] message: {}", responseMessage);


        // Response ์ƒ์„ฑ
        SampleResponse response = SampleResponse.newBuilder()
            .setMessage(responseMessage)
            .build();

        // ์‘๋‹ต ๋ฐ˜ํ™˜
        responseObserver.onNext(response);
        responseObserver.onCompleted();
    }
}

 

์—ฌ๊ธฐ์„œ SampleResponse์™€ SampleRequest๋Š” proto ํŒŒ์ผ์„ buildํ•˜๋ฉด์„œ ์ƒ์„ฑ๋œ ํด๋ž˜์Šค๋“ค์ด๋‹ค. 

 

 

 

- gRPC ํ˜ธ์ถœ (client)

@Service
@Slf4j
@RequiredArgsConstructor
public class GrpcClientService {

    @GrpcClient("local-grpc-server")
    private SampleServiceGrpc.SampleServiceBlockingStub sampleServiceBlockingStub;

    private final SampleClient sampleClient;

    public String sendMessage(String userId, String message) {
        SampleRequest request = SampleRequest.newBuilder()
            .setUserId(userId)
            .setMessage(message)
            .build();

        SampleResponse response = sampleServiceBlockingStub.sampleCall(request);

        log.info("[gRPC client] message: {}", response.getMessage());

        return response.getMessage();
    }
}

 

์Šคํ”„๋ง์—์„œ๋Š” @GrpcClient ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ gRPC Stub์„ Spring์˜ DI(Dependency Injection) ๋ฐฉ์‹์œผ๋กœ ์ฃผ์ž…๋ฐ›์•„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. gRPC ํด๋ผ์ด์–ธํŠธ๋ฅผ ๊ตฌ์„ฑํ•  ๋•Œ ํ•„์š”ํ•œ ์ฑ„๋„ ์ƒ์„ฑ, Stub ์ƒ์„ฑ ๋“ฑ์˜ ๊ณผ์ •์„ ์ž๋™ํ™”ํ•˜์—ฌ ๊ฐœ๋ฐœ ํŽธ์˜์„ฑ์„ ๋†’์—ฌ์ค€๋‹ค.

 

@GrpcClient ์–ด๋…ธํ…Œ์ด์…˜์€ ์„ค์ • ํŒŒ์ผ(application.yml)์— ์ •์˜๋œ gRPC ์„œ๋ฒ„ ์ •๋ณด์™€ ์—ฐ๊ฒฐํ•œ๋‹ค.

 

 

 

 

 

 

 

 

 

 

 

6. ์„ฑ๋Šฅ ๋น„๊ต

Thread Group ์„ค์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

 

 

gRPC ์š”์ฒญ

 

 

 

 

 

HTTP ์š”์ฒญ

 

 

 

 

gRPC์˜ ๊ฒฝ์šฐ 1175 TPS

HTTP์˜ ๊ฒฝ์šฐ 154 TPS

 

๋กœ ์ธก์ •๋๊ณ  gRPC๊ฐ€ HTTP๋ณด๋‹ค ์•ฝ 663%์˜ ๋น ๋ฅธ ์„ฑ๋Šฅ์„ ๋ณด์—ฌ์คฌ๋‹ค. ์‹ค์ œ๋กœ 2๋ฐฐ~10๋ฐฐ ๊ฐ€๋Ÿ‰ ๋น ๋ฅด๋‹ค๊ณ  ํ•œ๋‹ค.