๐ก gRPC์ Rest api์ ์ฐจ์ด์ ์ ์ ๋ฆฌํ๊ณ ์ฅ๋จ์ ์ ํ์ ํ์ฌ ์ํฉ์ ๋ง๊ฒ ์ ์ฉํฉ๋๋ค.
์คํธ๋ ์ค ํ ์คํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์กฐ์ฌํ๋ค๊ฐ ํน์ ํด๋ค๋ง gRPC๋ฅผ ์ง์ํ๊ณ , gRPC๋ฅผ ์ฌ์ฉ ์ค์ธ ์ฝ๋๋ฅผ ์ฐพ์๋ณด๋ ๊ฑฐ์ Go, Kotiin ๊ธฐ๋ฐ ์ฝ๋๋ค ๋ฐ์ ์๊ธธ๋ gRPC์ Rest api์ ์ฐจ์ด์ ์ด ๋ฌด์์ด๊ณ ์ธ์ ๋ฌด์ผ ์ฌ์ฉํด์ผ ํ๋์ง / JS๋ฅผ ํตํด ์์ฃผ ์ฌ์ฉํ์ง ์๋ ์ด์ ๊ฐ ์์ ์ง ๊ถ๊ธํด์ ์กฐ์ฌํด ๋ด ๋๋ค.
Rest api๋ ๊ธฐ์กด์ ๋ง์ด ์ฌ์ฉํด๋ณด์ จ์ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋ณ๋ ์ค๋ช ์์ด ๋์ด๊ฐ๊ฒ ์ต๋๋ค.
gRPC๋?
grpc๋ ๊ตฌ๊ธ์์ ๊ฐ๋ฐํ ์คํ์์ค ์๊ฒฉ ํ๋ก์์ ํธ์ถ(RPC) ์์คํ ์ด๋ฉฐ, ์ ์ก์ ์ํด HTTP/2 ๋ฅผ ์ฌ์ฉํ๊ณ ์ธํฐํ์ด์ค ์ ์ ์ธ์ด๋ก ํ๋กํ ์ฝ ๋ฒํผ๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
client - server side๋ก ๊ตฌ์ฑ๋๋ฉฐ, server side์์๋ ์ธํฐํ์ด์ค๋ฅผ ์ ์ํ๊ณ ์๋ฒ๋ฅผ ๊ตฌ๋ํ์ฌ client์ ์์ฒญ์ ๋ฐ๊ณ client side์์๋ stub๊ฐ ์ ๊ณตํ๋ ๋ฉ์๋๋ฅผ ์ด์ฉํ์ฌ ์๋ฒ์ ํต์ ํฉ๋๋ค.
gRPC ์ฌ์ฉ
gRPC๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด JS ๊ธฐ๋ฐ ์น ํด๋ผ์ด์ธํธ์์ ์ด๋ค ๊ณผ์ ์ ๊ฑฐ์ณ์ผ ํ๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
1. gRPC ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น
- protobuf: binary serialization format
- grpc : gRPC communication
- grpc-tools : .proto ํ์ผ๋ก๋ถํฐ client, server stub๋ฅผ ์์ฑํ๊ธฐ ์ํด ํ์ํ ์๋ธ ํด
โ stub๋ protobuf๋ก ์ ์๋ ์์ฒญ / ์๋ต ๋ฉ์์ง๋ค๋ก๋ถํฐ ์๋์ผ๋ก ์์ฑ๋๋ client ์ธก ์ธ์คํด์ค ์ ๋๋ค. ์ด๋ฅผ ์ด์ฉํ์ฌ ์ฐ๋ฆฌ๋ low-level์ ์๋ฆฌ๋ฅผ ์ ํ์ ์์ด ๋ณด๋ค ๋์ ๋ ๋ฒจ์ ์ธํฐํ์ด์ค๋ฅผ ์ด์ฉํด ํต์ ์ ์ํํ ์ ์์ต๋๋ค.
2. proto ํ์ผ ์์ฑ
.proto ํ์ผ์ IDL(Interface Definition Language)๋ฅผ ์ด์ฉํ์ฌ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ ์ํด ์ค๋๋ค. ์ฝ๊ฒ ๋งํด ํด๋น ํ์ผ์ด api ์ ์์ ์ญํ ์ ํฉ๋๋ค.
syntax = "proto3";
service MyService {
rpc MyMethod(MyRequest) returns (MyResponse) {}
}
message MyRequest {
string message = 1;
}
message MyResponse {
string message = 1;
}
3. (์ ํ) gRPC Client ์ฝ๋ ์์ฑ
protoc cli ๋ฅผ ์ด์ฉํ์ฌ js๋ก ๋ gRPC ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค. ์ด ํ์ผ์ ์ฐ๋ฆฌ๊ฐ JS ์ฝ๋ ์์์ ์ฌ์ฉํ ์ ์๋ stub๋ฅผ ๋ง๋ค์ด์ฃผ๋ ์ญํ ์ ํฉ๋๋ค.
4. JS ํต์ ์ฝ๋ ์์ฑ
const grpc = require('grpc');
const myService = require('./my_service_pb'); // 3๋ฒ์์ ๋ง๋ ํ์ผ
/* ์ด๋ ๊ฒ ์ง์ ์ฝ๋ ์์์ stub๋ฅผ ์์ฑํด๋ ๋จ
const packageDefinition = protoLoader.loadSync('path/to/your.proto');
const myService = grpc.loadPackageDefinition(packageDefinition).myService;
*/
// Create a client stub
const myServiceClient = new myService.MyServiceClient('localhost:50051', grpc.credentials.createInsecure());
// Invoke a remote method on the server
const request = new myService.MyRequest();
request.setMessage('Hello from gRPC client!');
myServiceClient.myMethod(request, (error, response) => {
if (error) {
console.error('Error:', error);
} else {
console.log('Response:', response.getMessage());
}
});
gRPC vs REST API
gRPC | REST API | |
performance | binary serialization์ ์ฌ์ฉํ๋ฏ๋ก ์์ payload๋ฅผ ์์ฑํ์ฌ ๋น ๋ฅธ ๋ฐ์ดํฐ ์ ์ก์ ํ ์ ์๋ค. | |
+) HTTP/2๋ฅผ ์ฌ์ฉํ์ฌ ๋ ์ข์ ์ฑ๋ฅ์ ๋ธ๋ค. | text serialization (e.g. JSON) ๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ๋น๊ต์ ๋๋ฆฌ๋ค. | |
interface | stub๋ฅผ ์์ฑํ๋ฉด ํธ๋ฆฌํ๊ฒ ์ด์ฉ ๊ฐ๋ฅํ๋ค. | fetch, axios ์ ๊ฐ์ web api๋ก ํธ๋ฆฌํ๊ฒ ์ด์ฉ ๊ฐ๋ฅํ๋ค. |
simplicity | HTTP/2 ๋ฅผ ์ฌ์ฉํ๊ณ protobuf ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ฏ๋ก ๋ฌ๋ ์ปค๋ธ๊ฐ ์ข ์๋ค. | HTTP์ ํ์ค ๋ฉ์๋๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ๋ฏ๋ก ์ฝ๋ค. |
debugging | grpc-web-devtools ๊ฐ์ ์ต์คํ ์ ์ ์ฌ์ฉํด์ผ ๊ฐ๋ฐ์ ๋๊ตฌ์์ ๋คํธ์ํฌ ์์ ์ ๋ณด๋ฅผ ํ์ธํ ์ ์๋ค. | ์น ๋ธ๋ผ์ฐ์ ์์ ๊ฐ๋ฐ์๋๊ตฌ๋ก ๋ณ๋ ์ฒ๋ฆฌ ์์ด ์์ฒญ, ์๋ต์ ํ์ธํ ์ ์๋ค. |
interoperability | ํน์ ์ธ์ด๋ค์ ์ฌ๋ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ค์ ์ ์ถ๊ฐํจ์ผ๋ก์จ ์ง์ํ๋ค. | ํ๋ซํผ์ด๋ ์ธ์ด์ ๊ธฐ๋ฐํ์ง ์๋๋ค. |
streaming | ์๋ฐฉํฅ streaming์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํ์ง๋ง gRPC-web์์๋ ์ง์ํ์ง ์๋๋ค. | ๊ธฐ๋ณธ์ ์ผ๋ก๋ ์ง์ํ์ง ์๊ณ ๋ณ๋์ ํด์ ์ด์ฉํด์ผ ํ๋ค. |
generate code | o | with tools |
gRPC๋ ๋์ ํผํฌ๋จผ์ค๋ฅผ ๋ด๋ฉฐ ์ฝ๋๋ฅผ ์์ฑํด์ค๋ค๋ ์ ์์ ์๋ฏธ๊ฐ ์์ง๋ง, ์ฌ์ฉํ๊ธฐ ์ฌ์ฐ๋ฉฐ ๊ธฐ์กด ์์คํ ๊ณผ ์ํธ์ด์ฉ์ ์ด๊ณ ์ด๋ฏธ REST API์ ์ต์ํ ํ์ด๋ผ๋ฉด REST API๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ซ์ต๋๋ค. ๊ฐ์ธ์ ์ผ๋ก gRPC๋ฅผ ์ฌ์ฉํ ๋ ๋๋ฒ๊น ๋ฐ ๊ฐ๋ฐ ์ ๋๋ฌด ๋ง์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ + ํด์ ์์กดํด์ผ ํ๋ ๊ฒ๋ ๋จ์ ์ธ ๊ฒ ๊ฐ์ต๋๋ค.
Appendix
https://grpc.io/docs/what-is-grpc/introduction/
https://bourbonkk.tistory.com/109
https://chacha95.github.io/2020-06-16-gRPC2/
https://learn.microsoft.com/ko-kr/aspnet/core/grpc/comparison?view=aspnetcore-7.0
Chatgpt
๋ถ์ ํํ ์ ๋ณด๊ฐ ๋ด๊ฒจ์์ ์ ์์ต๋๋ค!
๋๊ธ๋ก ์๋ ค์ฃผ์ธ์ :)
Comment