โ Back to list

grpc-service
by eco2-team
๐ฑ ์ด์ฝ์์ฝ(Ecoยฒ) BE
โญ 0๐ด 0๐
Jan 25, 2026
SKILL.md
name: grpc-service description: gRPC ์๋น์ค ํตํฉ ๊ฐ์ด๋. Port/Adapter ํจํด, Proto ์ ์, Async Client ๊ตฌํ ์ ์ฐธ์กฐ. "grpc", "proto", "subagent", "character", "location", "rpc" ํค์๋๋ก ํธ๋ฆฌ๊ฑฐ.
gRPC Service Integration Guide
Ecoยฒ gRPC ํตํฉ ์ํคํ ์ฒ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ gRPC Integration (Clean Architecture) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Application Layer (Ports) โ
โ โโ CharacterClientPort (Protocol) โ
โ โโ LocationClientPort (Protocol) โ
โ โโ DTOs: CharacterDTO, LocationDTO โ
โ โ โ
โ โผ โ
โ Infrastructure Layer (Adapters) โ
โ โโ CharacterGrpcClient โโโ character-api:50051 โ
โ โโ LocationGrpcClient โโโ location-api:50051 โ
โ โ โ
โ โผ โ
โ Proto Files (Contract) โ
โ โโ character.proto โ character_pb2.py, character_pb2_grpc.py โ
โ โโ location.proto โ location_pb2.py, location_pb2_grpc.py โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
์ gRPC์ธ๊ฐ? (vs HTTP/Celery)
| Aspect | HTTP | Celery | gRPC |
|---|---|---|---|
| Latency | ~10ms | ~50ms+ | ~1-3ms |
| Type Safety | ๋ฐํ์ | ์์ | ์ปดํ์ผํ์ |
| Asyncio | ์ ํ์ | ๋ฏธ์ง์ | ๋ค์ดํฐ๋ธ |
| Streaming | ๋ณต์ก | ๋ฏธ์ง์ | ๊ธฐ๋ณธ ์ง์ |
| LangGraph ํตํฉ | OK | await ๋ถ๊ฐ | ์ต์ |
Reference Files
- Port ์ ์: See port-definition.md
- Client ๊ตฌํ: See client-implementation.md
- Proto ๊ฐ์ด๋: See proto-guide.md
- ํ ์คํธ ํจํด: See testing-patterns.md
Quick Start
1. Port ์ ์ (Application Layer)
# application/ports/character_client.py
from abc import ABC, abstractmethod
from dataclasses import dataclass
@dataclass(frozen=True)
class CharacterDTO:
"""์บ๋ฆญํฐ ์ ๋ณด DTO"""
name: str
character_type: str
dialog: str
match_label: str
class CharacterClientPort(ABC):
"""์บ๋ฆญํฐ ์๋น์ค ํด๋ผ์ด์ธํธ Port"""
@abstractmethod
async def get_character_by_waste_category(
self,
waste_category: str,
) -> CharacterDTO | None:
"""ํ๊ธฐ๋ฌผ ์นดํ
๊ณ ๋ฆฌ๋ก ์บ๋ฆญํฐ ์กฐํ"""
...
@abstractmethod
async def get_catalog(self) -> list[CharacterDTO]:
"""์ ์ฒด ์บ๋ฆญํฐ ๋ชฉ๋ก ์กฐํ"""
...
2. gRPC Client ๊ตฌํ (Infrastructure Layer)
# infrastructure/integrations/character/grpc_client.py
import grpc.aio
from .proto import character_pb2, character_pb2_grpc
class CharacterGrpcClient(CharacterClientPort):
"""gRPC ๊ธฐ๋ฐ ์บ๋ฆญํฐ ํด๋ผ์ด์ธํธ"""
def __init__(self, host: str = "character-api", port: int = 50051):
self._host = host
self._port = port
self._channel: grpc.aio.Channel | None = None
self._stub: character_pb2_grpc.CharacterServiceStub | None = None
async def _get_stub(self) -> character_pb2_grpc.CharacterServiceStub:
"""Lazy ์ฐ๊ฒฐ (์ฒซ ํธ์ถ ์ ์ฑ๋ ์์ฑ)"""
if self._stub is None:
self._channel = grpc.aio.insecure_channel(
f"{self._host}:{self._port}"
)
self._stub = character_pb2_grpc.CharacterServiceStub(self._channel)
return self._stub
async def get_character_by_waste_category(
self,
waste_category: str,
) -> CharacterDTO | None:
try:
stub = await self._get_stub()
request = character_pb2.GetByMatchRequest(
match_label=waste_category
)
response = await stub.GetCharacterByMatch(request)
if not response.found:
return None
return CharacterDTO(
name=response.name,
character_type=response.character_type,
dialog=response.dialog,
match_label=response.match_label,
)
except grpc.aio.AioRpcError as e:
logger.error("gRPC error", code=e.code().name, details=e.details())
return None
async def close(self) -> None:
"""์ฑ๋ ์ข
๋ฃ"""
if self._channel:
await self._channel.close()
self._channel = None
self._stub = None
3. LangGraph ๋ ธ๋ ํตํฉ
# infrastructure/orchestration/langgraph/nodes/character_node.py
def create_character_node(
character_client: CharacterClientPort,
llm: LLMClientPort,
) -> Callable:
"""์บ๋ฆญํฐ Subagent ๋
ธ๋ ์์ฑ"""
async def character_node(state: dict) -> dict:
query = state["query"]
# LLM์ผ๋ก ํ๊ธฐ๋ฌผ ์นดํ
๊ณ ๋ฆฌ ์ถ์ถ
category = await extract_waste_category(llm, query)
# gRPC ํธ์ถ
character = await character_client.get_character_by_waste_category(
category
)
return {
"character_context": character.__dict__ if character else None,
}
return character_node
4. ์์กด์ฑ ์ฃผ์
# setup/dependencies.py
from functools import lru_cache
@lru_cache
def get_character_client() -> CharacterClientPort:
settings = get_settings()
return CharacterGrpcClient(
host=settings.character_grpc_host,
port=settings.character_grpc_port,
)
async def cleanup():
"""์ ํ๋ฆฌ์ผ์ด์
์ข
๋ฃ ์ ๋ฆฌ์์ค ์ ๋ฆฌ"""
client = get_character_client()
await client.close()
Score
Total Score
60/100
Based on repository quality metrics
โSKILL.md
SKILL.mdใใกใคใซใๅซใพใใฆใใ
+20
โLICENSE
ใฉใคใปใณในใ่จญๅฎใใใฆใใ
+10
โ่ชฌๆๆ
100ๆๅญไปฅไธใฎ่ชฌๆใใใ
0/10
โไบบๆฐ
GitHub Stars 100ไปฅไธ
0/15
โๆ่ฟใฎๆดปๅ
3ใถๆไปฅๅ ใซๆดๆฐใใใ
0/10
โใใฉใผใฏ
10ๅไปฅไธใใฉใผใฏใใใฆใใ
0/5
โIssue็ฎก็
ใชใผใใณIssueใ50ๆชๆบ
+5
โ่จ่ช
ใใญใฐใฉใใณใฐ่จ่ชใ่จญๅฎใใใฆใใ
+5
โใฟใฐ
1ใคไปฅไธใฎใฟใฐใ่จญๅฎใใใฆใใ
0/5
Reviews
๐ฌ
Reviews coming soon