๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  • ๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป ๐ŸŒฎ ๐Ÿ’ฌ
๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป/gRPC

[python] gRPC ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•ด๋ณด๊ธฐ

by ๋ฐ”์ฟ„๋ฆฌ 2025. 1. 2.

 

๋„คํŠธ์›Œํฌ ํ†ต์‹  ํ”„๋กœํ† ์ฝœ gRPC์™€ websocket์„ ๋น„๊ตํ•ด๋ณด์•˜๋‹ค

 

[gRPC] gRPC๊ณผ websocket ๋น„๊ต ์ •๋ฆฌ

๊ธฐ์กด์— ๊ฐœ๋ฐœํ–ˆ๋˜ ์„œ๋น„์Šค์—์„œ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ํ†ต์‹ ์„ websocket ์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค.๋‹ค ๋๋‚ด๊ณ ๋‚˜์„œ ํด๋ผ์ด์–ธํŠธ, ์„œ๋ฒ„ ํ†ต์‹ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ข€ ๋” ์„œ์น˜ํ•ด๋ณด๊ณ  ์‹ถ์—ˆ๋‹ค๊ทธ๋ ‡๊ฒŒ ์•Œ๊ฒŒ๋œ gRPC. ์ •๋ฆฌํ•ด๋ณด์ž โœ… gRPC

bonory.tistory.com

 

์ต์ˆ™ํ•˜์ง€ ์•Š์€ gRPC๋ฅผ python์œผ๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•ด๋ณด์•˜๋‹ค

 

1. Protocol Buffers (Protobuf) ์ •์˜

gRPC์˜ ํ•ต์‹ฌ์€ API ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•˜๋Š” Protobuf ํŒŒ์ผ์ด๋‹ค!

.proto ํŒŒ์ผ ์ž‘์„ฑํ•œ๋‹ค = ์„œ๋น„์Šค์™€ ๋ฉ”์‹œ์ง€์˜ ์Šคํ‚ค๋งˆ๋ฅผ ์ •์˜ํ•œ๋‹ค

 

greeter.proto

syntax = "proto3";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

message HelloRequest {
  string name = 1;
}

message HelloResponse {
  string message = 1;
}

 

2. gRPC ์ปดํŒŒ์ผ๋Ÿฌ(protoc)๋ฅผ ์‚ฌ์šฉํ•ด ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑ

2-1. Protocol Buffers ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด ์„ค์น˜ํ•œ๋‹ค.

# Mac
brew install protobuf

 

2-2. ํŒจํ‚ค์ง€๋„ ์„ค์น˜ํ•œ๋‹ค.

pip install --upgrade grpcio grpcio-tools

 

2-3. ์„œ๋ฒ„, ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ ์ƒ์„ฑํ•œ๋‹ค.

protoc --proto_path=. --python_out=. --grpc_python_out=. greeter.proto

# ์ง์ ‘ grpc_tools.protoc ๋ชจ๋“ˆ์„ Python ๋ช…๋ น์–ด๋กœ ์‹คํ–‰
python -m grpc_tools.protoc -I=. --python_out=. --grpc_python_out=. greeter.proto

 

๋ช…๋ น์–ด๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋˜๋ฉด ํŒŒ์ผ์ด 2๊ฐœ ์ƒ์„ฑ๋œ๋‹ค.

  1. greeter_pb2.py
    1. Protocol Buffers ๋ฉ”์‹œ์ง€ ํด๋ž˜์Šค ์ •์˜
    2. .proto ํŒŒ์ผ์— ์ •์˜๋œ ๋ฉ”์‹œ์ง€(message)์™€ ๊ด€๋ จ๋œ Python ํด๋ž˜์Šค๋“ค์ด ํฌํ•จํ•œ๋‹ค.
    3. ์˜ˆ: HelloRequest, HelloResponse
  2. greeter_pb2_grpc.py
    1. gRPC ์„œ๋น„์Šค Stub ๋ฐ ์„œ๋ฒ„ ์ธํ„ฐํŽ˜์ด์Šค ์ •์˜
    2. ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” gRPC ๋ฉ”์„œ๋“œ Stub๊ณผ ์„œ๋น„์Šค ํด๋ž˜์Šค๋ฅผ ํฌํ•จํ•œ๋‹ค.
    3. ์˜ˆ: GreeterStub (ํด๋ผ์ด์–ธํŠธ์šฉ), GreeterServicer (์„œ๋ฒ„์šฉ)

3. ์ƒ์„ฑ๋œ ํŒŒ์ผ์„ ๊ธฐ์ค€์œผ๋กœ ์„œ๋ฒ„, ํด๋ผ์ด์–ธํŠธ ํŒŒ์ผ ์ž‘์„ฑ

server.py

from concurrent import futures
import grpc
import greeter_pb2
import greeter_pb2_grpc

class GreeterService(greeter_pb2_grpc.GreeterServicer):
    def SayHello(self, request, context):
        print(f"Received request: {request.name}")
        return greeter_pb2.HelloResponse(message=f"Hello, {request.name}!")

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    greeter_pb2_grpc.add_GreeterServicer_to_server(GreeterService(), server)
    server.add_insecure_port('[::]:50051')
    print("Server started on port 50051")
    server.start()
    server.wait_for_termination()

if __name__ == '__main__':
    serve()

 

client.py

import grpc
import greeter_pb2
import greeter_pb2_grpc

channel = grpc.insecure_channel('localhost:50051')
stub = greeter_pb2_grpc.GreeterStub(channel)
response = stub.SayHello(greeter_pb2.HelloRequest(name="World"))
print(response.message)

 

+ ํŒŒ์ผ ๊ตฌ์„ฑ ์˜ˆ์‹œ

gRPC_test/
โ”œโ”€โ”€ greeter.proto        # .proto ํŒŒ์ผ
โ”œโ”€โ”€ greeter_pb2.py       # protoc์— ์˜ํ•ด ์ƒ์„ฑ๋œ ํŒŒ์ผ (Protocol Buffers ๋ฉ”์‹œ์ง€ ํด๋ž˜์Šค)
โ”œโ”€โ”€ greeter_pb2_grpc.py  # protoc์— ์˜ํ•ด ์ƒ์„ฑ๋œ ํŒŒ์ผ (gRPC Stub ๋ฐ ์„œ๋น„์Šค ์ธํ„ฐํŽ˜์ด์Šค)
โ”œโ”€โ”€ server.py            # ์„œ๋ฒ„ ์ฝ”๋“œ
โ””โ”€โ”€ client.py            # ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ

 

4. ์‹คํ–‰

 

1. ์„œ๋ฒ„ ์‹คํ–‰

python3 server.py
> Server started on port 50051

 

2. ํด๋ผ์ด์–ธํŠธ ์‹คํ–‰

python3 client.py
> Hello, World!

 

ํด๋ผ์ด์–ธํŠธ ์‹คํ–‰ํ–ˆ์„ ๋•Œ, ์„œ๋ฒ„ ์ชฝ์—๋„ ์•„๋ž˜์™€ ๊ฐ™์ด ์ฐํžˆ๋ฉด ์™„์„ฑ!

Received request: World

์™ผ: server.py โ˜ ์˜ค : client.py

 


โœ… ํด๋ผ์ด์–ธํŠธ PC์— ํ•„์š”ํ•œ ํŒŒ์ผ

  1. client.py: ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ
  2. greeter_pb2.py: protoc์— ์˜ํ•ด ์ƒ์„ฑ๋œ Protocol Buffers ๋ฉ”์‹œ์ง€ ํด๋ž˜์Šค ํŒŒ์ผ
  3. greeter_pb2_grpc.py: protoc์— ์˜ํ•ด ์ƒ์„ฑ๋œ gRPC Stub ์ •์˜ ํŒŒ์ผ

โœ… ์„œ๋ฒ„ PC์— ํ•„์š”ํ•œ ํŒŒ์ผ

  1. server.py: ์„œ๋ฒ„ ์ฝ”๋“œ
  2. greeter_pb2.py: protoc์— ์˜ํ•ด ์ƒ์„ฑ๋œ Protocol Buffers ๋ฉ”์‹œ์ง€ ํด๋ž˜์Šค ํŒŒ์ผ
  3. greeter_pb2_grpc.py: protoc์— ์˜ํ•ด ์ƒ์„ฑ๋œ gRPC Stub ์ •์˜ ํŒŒ์ผ
  4. greeter.proto: ํ•„์š” ์‹œ ์„œ๋ฒ„ ์ธก์—์„œ .proto ํŒŒ์ผ์„ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‹ค์‹œ ์ปดํŒŒ์ผํ•  ๊ฒฝ์šฐ

์„œ๋ฒ„, ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ ์ƒ์„ฑํ•˜๋Š” ๋ถ€๋ถ„์—์„œ ์ž๊พธ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ์žˆ์—ˆ๋‹ค โ€ผ๏ธ

/Users/~/protoc-gen-grpc_python: program not found or is not executable
Please specify a program using absolute path or make sure the program is available in your PATH system variable
--grpc_python_out: protoc-gen-grpc_python: Plugin failed with status code 1.

→ protoc๊ฐ€ gRPC Python ํ”Œ๋Ÿฌ๊ทธ์ธ(protoc-gen-grpc_python)์„ ์ฐพ์ง€ ๋ชปํ–ˆ๊ฑฐ๋‚˜ ์‹คํ–‰ ๊ถŒํ•œ์ด ์—†๋Š” ๊ฒฝ์šฐ ๋ฐœ์ƒ

→ ์‹คํ–‰๋˜์–ด์•ผ ํ•  protoc-gen-grpc_python ์ด /Users/~/venv/bin ์— ์„ค์น˜๊ฐ€ ์•ˆ๋˜์–ด์žˆ์—ˆ๋‹ค

๊ทธ๋ž˜์„œ ์ง์ ‘ ์ƒ์„ฑํ•ด์คฌ๋‹ค

 

1. /Users/~/venv/bin/protoc-gen-grpc_python ํŒŒ์ผ์„ ์ƒ์„ฑ

2. ์ƒ์„ฑํ•œ ํŒŒ์ผ์— ๋‚ด์šฉ ์ถ”๊ฐ€

#!/bin/bash
exec /Users/~/venv/bin/python -m grpc_tools.protoc "$@"

 

3. ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ

chmod +x /Users/~/venv/bin/protoc-gen-grpc_python

 

๊ทธ ๋‹ค์Œ์— protoc๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„, ํด๋ผ์ด์–ธํŠธ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋ฉด ๋˜๋Š”๋ฐ

protoc --proto_path=. --python_out=. --grpc_python_out=. greeter.proto

 

์•„๋ž˜์™€ ๊ฐ™์€ ์—๋Ÿฌ ๋ฉ”์„ธ์ง€๊ฐ€ ์ถœ๋ ฅ๋˜์—ˆ๋‹ค

Missing input file.
--grpc_python_out: protoc-gen-grpc_python: Plugin failed with status code 1.

 

์ง์ ‘ grpc_tools.protoc ๋ชจ๋“ˆ์„ python ๋ช…๋ น์–ด๋กœ ์‹คํ–‰ํ–ˆ๋‹ค

python -m grpc_tools.protoc -I=. --python_out=. --grpc_python_out=. greeter.proto

 

→ ๊ทธ์ œ์„œ์•ผ ์„œ๋ฒ„, ํด๋ผ์ด์–ธํŠธ ํŒŒ์ผ์ด ์ž˜ ์ƒ์„ฑ๋œ ๊ฑธ ํ™•์ธํ–ˆ๋‹ค ๐Ÿฅฒ ๐Ÿ‘

'๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป > gRPC' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

RPC vs gRPC  (0) 2025.01.14