๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

AI ๊ฐœ๋ฐœ

gRPC ๋ž€ ๋ฌด์—‡์ธ๊ฐ€? gRPC ํ™œ์šฉ ์‚ฌ๋ก€์™€ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•

๋ฐ˜์‘ํ˜•

๐Ÿš€ gRPC๋ž€ ๋ฌด์—‡์ด๊ณ , ์–ด๋–ป๊ฒŒ ์‹ค๋ฌด์—์„œ ํ™œ์šฉ๋˜๋Š”๊ฐ€?

1๏ธโƒฃ ์‹ค๋ฌด ํ™œ์šฉ ์‚ฌ๋ก€: ์™œ gRPC์ธ๊ฐ€?

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

๐Ÿ’ฌ 1. ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ์‹œ์Šคํ…œ

  • Slack, Zoom, Discord์™€ ๊ฐ™์€ ๋ฉ”์‹œ์ง• ์„œ๋น„์Šค๋Š” ์‚ฌ์šฉ์ž ๊ฐ„์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ง€์—ฐ ์—†์ด ์ฃผ๊ณ ๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • gRPC์˜ ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆฌ๋ฐ์€ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ํ•˜๋‚˜์˜ ์—ฐ๊ฒฐ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ๋™์‹œ์— ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

๐Ÿ“ก 2. IoT ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง

  • ์„ผ์„œ๊ฐ€ ์„œ๋ฒ„์— ์ง€์†์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๊ณ , ์„œ๋ฒ„๋Š” ์‹ค์‹œ๊ฐ„ ์ œ์–ด ์‹ ํ˜ธ๋ฅผ ๋‹ค์‹œ ์„ผ์„œ๋กœ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ˆ: ์Šค๋งˆํŠธ ๊ณต์žฅ, ๋“œ๋ก  ์ œ์–ด ์‹œ์Šคํ…œ, ํ—ฌ์Šค์ผ€์–ด ๋ชจ๋‹ˆํ„ฐ๋ง ๋“ฑ

๐ŸŽฎ 3. ๋ฉ€ํ‹ฐํ”Œ๋ ˆ์ด์–ด ๊ฒŒ์ž„ ์„œ๋ฒ„

  • ํ”Œ๋ ˆ์ด์–ด ๊ฐ„ ์œ„์น˜, ์ƒํƒœ, ์ด๋ฒคํŠธ ๋™๊ธฐํ™”๊ฐ€ ๋ฐ€๋ฆฌ์ดˆ ๋‹จ์œ„๋กœ ์ด๋ฃจ์–ด์ ธ์•ผ ํ•˜๋Š” ํ™˜๊ฒฝ์—์„œ๋Š”, gRPC ์ŠคํŠธ๋ฆฌ๋ฐ์ด REST๋ณด๋‹ค ํ›จ์”ฌ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

๐ŸŽ™๏ธ 4. ์‹ค์‹œ๊ฐ„ ์Œ์„ฑ/ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ

  • ์‚ฌ์šฉ์ž์˜ ๋งˆ์ดํฌ ์ž…๋ ฅ์„ ์ง€์†์ ์œผ๋กœ ๋ณด๋‚ด๊ณ , ์„œ๋ฒ„๋Š” ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ…์ŠคํŠธ๋กœ ๋ณ€ํ™˜(STT).
  • Google Speech-to-Text, Amazon Transcribe ๋“ฑ์˜ ์‹ค์ œ ์„œ๋น„์Šค๋“ค์ด gRPC ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์Œ

๐Ÿ’น 5. ๊ธˆ์œต ๋ฐ์ดํ„ฐ ์ „์†ก

  • ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ฃผ์‹ ์ฒด๊ฒฐ ์ •๋ณด, ์‹œ์„ธ ๋ณ€๋™ ๋“ฑ์„ ๋ฐ›์•„์•ผ ํ•˜๋Š” ๊ธˆ์œต ์„œ๋น„์Šค๋Š” gRPC๋ฅผ ํ†ตํ•ด ๊ตฌ๋… ๊ธฐ๋ฐ˜ ์ŠคํŠธ๋ฆฌ๋ฐ ์ฒ˜๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•จ

2๏ธโƒฃ gRPC๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

๐Ÿ“ฆ ์ •์˜

gRPC๋Š” Google์ด ๊ฐœ๋ฐœํ•œ ๊ณ ์„ฑ๋Šฅ ์›๊ฒฉ ํ”„๋กœ์‹œ์ € ํ˜ธ์ถœ(Remote Procedure Call) ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค.
๊ธฐ์กด์˜ REST API ๋ฐฉ์‹๊ณผ ๋‹ฌ๋ฆฌ, ํ•จ์ˆ˜ ํ˜ธ์ถœ์ฒ˜๋Ÿผ ์„œ๋ฒ„์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“Œ ํŠน์ง• ์š”์•ฝ

ํ•ญ๋ชฉ ์„ค๋ช…
๋ฐ์ดํ„ฐ ํฌ๋งท JSON ๋Œ€์‹  Protobuf (Protocol Buffers) ์‚ฌ์šฉ
์†๋„ ํ…์ŠคํŠธ ๊ธฐ๋ฐ˜๋ณด๋‹ค ์ž‘๊ณ  ๋น ๋ฆ„
์—ฐ๊ฒฐ ๋ฐฉ์‹ HTTP/2 ๊ธฐ๋ฐ˜ – ํ•˜๋‚˜์˜ ์—ฐ๊ฒฐ๋กœ ์—ฌ๋Ÿฌ ์š”์ฒญ ์ฒ˜๋ฆฌ
ํ†ต์‹  ํŒจํ„ด ์š”์ฒญ-์‘๋‹ต, ์„œ๋ฒ„ ์ŠคํŠธ๋ฆฌ๋ฐ, ํด๋ผ์ด์–ธํŠธ ์ŠคํŠธ๋ฆฌ๋ฐ, ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆฌ๋ฐ ์ง€์›
์ž๋™ ์ฝ”๋“œ ์ƒ์„ฑ .proto ํŒŒ์ผ๋กœ๋ถ€ํ„ฐ ๋‹ค๊ตญ์–ด ํด๋ผ์ด์–ธํŠธ/์„œ๋ฒ„ ์ฝ”๋“œ ์ž๋™ ์ƒ์„ฑ

๐Ÿ“˜ ํ•ต์‹ฌ ๊ฐœ๋…: .proto ํŒŒ์ผ

syntax = "proto3";

service Translator {
  rpc Translate (TextInput) returns (TextOutput);
}

message TextInput {
  string text = 1;
  string lang = 2;
}

message TextOutput {
  string translated_text = 1;
}

์œ„์™€ ๊ฐ™์ด ์„œ๋น„์Šค(Translator) ์™€ ๋ฉ”์‹œ์ง€ ๊ตฌ์กฐ๋ฅผ ์ •์˜ํ•˜๋ฉด, protoc ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด Python, Java, Go ๋“ฑ ๋‹ค์–‘ํ•œ ์–ธ์–ด๋กœ ์ž๋™ ์ฝ”๋“œ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.


3๏ธโƒฃ Python์œผ๋กœ gRPC ๊ตฌํ˜„ํ•˜๊ธฐ – ์‹ค์ „ ์˜ˆ์ œ

์ด์ œ ์‹ค์ œ๋กœ gRPC ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๋ฅผ Python์œผ๋กœ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
์šฐ๋ฆฌ๊ฐ€ ๊ตฌํ˜„ํ•  ์˜ˆ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

๐ŸŽฏ ๋ชฉํ‘œ: ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฌธ์ž์—ด์„ ๋ณด๋‚ด๋ฉด, ์„œ๋ฒ„๊ฐ€ ํ•ด๋‹น ๋ฌธ์ž์—ด์„ ๋Œ€๋ฌธ์ž๋กœ ๋ฐ”๊ฟ”์„œ ๋Œ๋ ค์ฃผ๋Š” ๊ฐ„๋‹จํ•œ ์„œ๋น„์Šค
SayHello("hello")HELLO


๐Ÿงฑ 1๋‹จ๊ณ„: .proto ํŒŒ์ผ ์ž‘์„ฑ

hello.proto ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:

syntax = "proto3";

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

message HelloRequest {
  string message = 1;
}

message HelloResponse {
  string message = 1;
}
  • SayHello๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋ฉด ์„œ๋ฒ„๊ฐ€ ์‘๋‹ตํ•˜๋Š” ๋‹จ๋ฐฉํ–ฅ RPC
  • HelloRequest, HelloResponse๋Š” ์š”์ฒญ/์‘๋‹ต ๋ฉ”์‹œ์ง€ ๊ตฌ์กฐ

โš™๏ธ 2๋‹จ๊ณ„: Python ์ฝ”๋“œ ์ž๋™ ์ƒ์„ฑ

โ‘  protoc ์„ค์น˜ (ํ•œ ๋ฒˆ๋งŒ)

python -m pip install grpcio grpcio-tools

โ‘ก ์ž๋™ ์ƒ์„ฑ ์‹คํ–‰

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

์‹คํ–‰ ๊ฒฐ๊ณผ:

  • hello_pb2.py (๋ฉ”์‹œ์ง€ ์ •์˜)
  • hello_pb2_grpc.py (gRPC ์„œ๋ฒ„/ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ)

๐Ÿ–ฅ๏ธ 3๋‹จ๊ณ„: gRPC ์„œ๋ฒ„ ๊ตฌํ˜„

server.py:

from concurrent import futures
import grpc
import hello_pb2
import hello_pb2_grpc

class HelloService(hello_pb2_grpc.HelloServiceServicer):
    def SayHello(self, request, context):
        reply = request.message.upper()
        return hello_pb2.HelloResponse(message=reply)

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

if __name__ == '__main__':
    serve()

๐Ÿ’ป 4๋‹จ๊ณ„: gRPC ํด๋ผ์ด์–ธํŠธ ๊ตฌํ˜„

client.py:

import grpc
import hello_pb2
import hello_pb2_grpc

def run():
    channel = grpc.insecure_channel('localhost:50051')
    stub = hello_pb2_grpc.HelloServiceStub(channel)
    response = stub.SayHello(hello_pb2.HelloRequest(message="hello grpc"))
    print("Response from server:", response.message)

if __name__ == '__main__':
    run()

โœ… ์‹คํ–‰ ์ˆœ์„œ

  1. ์„œ๋ฒ„ ๋จผ์ € ์‹คํ–‰:
  2. python server.py
  3. ํด๋ผ์ด์–ธํŠธ ์‹คํ–‰:
  4. python client.py
  5. ๊ฒฐ๊ณผ:
  6. Response from server: HELLO GRPC

๐Ÿ” Python์œผ๋กœ ๊ตฌํ˜„ํ•˜๋Š” gRPC ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆฌ๋ฐ ์˜ˆ์ œ

๐ŸŽฏ ๋ชฉํ‘œ ์‹œ๋‚˜๋ฆฌ์˜ค

ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ์ฑ„ํŒ…ํ•˜๋“ฏ ๋™์‹œ์— ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š” ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด ๋ด…๋‹ˆ๋‹ค.
ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฌธ์žฅ์„ ํ•œ ์ค„์”ฉ ๋ณด๋‚ด๋ฉด, ์„œ๋ฒ„๋Š” ๊ทธ๊ฒƒ์„ ๋Œ€๋ฌธ์ž๋กœ ๋ฐ”๊ฟ”์„œ ๋ฐ”๋กœ๋ฐ”๋กœ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.
์—ฌ๋Ÿฌ ์ค„์„ ์ฃผ๊ณ ๋ฐ›๋Š” ๋™์•ˆ ์—ฐ๊ฒฐ์€ ๊ณ„์† ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.


๐Ÿ“ฆ 1๋‹จ๊ณ„: .proto ํŒŒ์ผ ์ •์˜

chat.proto

syntax = "proto3";

service ChatService {
  rpc Chat(stream ChatMessage) returns (stream ChatMessage);
}

message ChatMessage {
  string sender = 1;
  string message = 2;
}
  • rpc Chat(...) returns (...) ๊ตฌ์กฐ๋ฅผ ๋ณด๋ฉด ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆฌ๋ฐ์ž„์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ChatMessage๋Š” ์ฑ„ํŒ…์˜ ๊ธฐ๋ณธ ๋‹จ์œ„ ๋ฉ”์‹œ์ง€

โš™๏ธ 2๋‹จ๊ณ„: Python ์ฝ”๋“œ ์ž๋™ ์ƒ์„ฑ

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

chat_pb2.py, chat_pb2_grpc.py ์ƒ์„ฑ๋จ


๐Ÿ–ฅ๏ธ 3๋‹จ๊ณ„: ์„œ๋ฒ„ ๊ตฌํ˜„

chat_server.py

import grpc
from concurrent import futures
import time
import chat_pb2
import chat_pb2_grpc

class ChatService(chat_pb2_grpc.ChatServiceServicer):
    def Chat(self, request_iterator, context):
        for chat in request_iterator:
            print(f"[{chat.sender}]: {chat.message}")
            response = chat_pb2.ChatMessage(
                sender="Server",
                message=chat.message.upper()
            )
            yield response

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    chat_pb2_grpc.add_ChatServiceServicer_to_server(ChatService(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    print("Server listening on port 50051...")
    server.wait_for_termination()

if __name__ == '__main__':
    serve()

๐Ÿ’ป 4๋‹จ๊ณ„: ํด๋ผ์ด์–ธํŠธ ๊ตฌํ˜„

chat_client.py

import grpc
import chat_pb2
import chat_pb2_grpc

def generate_messages():
    sender_name = input("Enter your name: ")
    while True:
        msg = input("You: ")
        if msg.lower() == 'exit':
            break
        yield chat_pb2.ChatMessage(sender=sender_name, message=msg)

def run():
    channel = grpc.insecure_channel('localhost:50051')
    stub = chat_pb2_grpc.ChatServiceStub(channel)
    responses = stub.Chat(generate_messages())
    for res in responses:
        print(f"{res.sender}: {res.message}")

if __name__ == '__main__':
    run()

๐Ÿงช ์‹คํ–‰ ์˜ˆ์‹œ

  1. ์„œ๋ฒ„ ์‹คํ–‰
  2. python chat_server.py
  3. ํด๋ผ์ด์–ธํŠธ ์‹คํ–‰
  4. python chat_client.py
  5. ์‚ฌ์šฉ ์˜ˆ
  6. Enter your name: Alice You: hello Server: HELLO You: grpc is cool Server: GRPC IS COOL
  7. ์ข…๋ฃŒ๋Š” exit ์ž…๋ ฅ์œผ๋กœ.

โœ… ์‹ค๋ฌด์—์„œ ์ด๋ ‡๊ฒŒ ์‘์šฉ๋ฉ๋‹ˆ๋‹ค

์‹ค๋ฌด ์‚ฌ๋ก€ ํ™œ์šฉ ๋ฐฉ์‹
์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€๋ฅผ ์„œ๋ฒ„๊ฐ€ ๋ณ€ํ˜•/์ค‘๊ณ„
์Œ์„ฑ ์ฒ˜๋ฆฌ ์Œ์„ฑ ์ŠคํŠธ๋ฆผ์„ ์„œ๋ฒ„์— ๋ณด๋‚ด๊ณ , ์‹ค์‹œ๊ฐ„ ํ…์ŠคํŠธ๋กœ ๋ฐ›์Œ
๊ฒŒ์ž„ ์„œ๋ฒ„ ํ”Œ๋ ˆ์ด์–ด ์ƒํƒœ๋ฅผ ์ŠคํŠธ๋ฆฌ๋ฐ์œผ๋กœ ์ฃผ๊ณ ๋ฐ›์Œ
IoT ์žฅ๋น„ ์„ผ์„œ ↔ ์ œ์–ด ๋ช…๋ น์„ ์—ฐ์†์ ์œผ๋กœ ์†ก์ˆ˜์‹ 

๐Ÿง  ๋งˆ๋ฌด๋ฆฌ ์š”์•ฝ

  • gRPC ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆฌ๋ฐ์€ ๋‹จ์ผ ์—ฐ๊ฒฐ๋กœ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ๊ตฌ์กฐ์— ๊ฐ•๋ ฅํ•จ
  • yield๋ฅผ ํ†ตํ•ด ๋ฉ”์‹œ์ง€๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ฃผ๊ณ ๋ฐ›์Œ
  • REST API๋ณด๋‹ค ํšจ์œจ์ ์ด๊ณ  ๋ฐ˜์‘์„ฑ์ด ๋›ฐ์–ด๋‚จ

๋ฐ˜์‘ํ˜•