1. 소개
이 Codelab에서는 gRPC-Python을 사용하여 Python으로 작성된 경로 매핑 애플리케이션의 기반을 형성하는 클라이언트와 서버를 만듭니다.
튜토리얼이 끝나면 gRPC를 사용하여 원격 서버에 연결하여 지도에서 특정 좌표에 있는 항목의 이름이나 우편 주소를 가져오는 클라이언트가 있습니다. 완전한 애플리케이션은 이 클라이언트-서버 설계를 사용하여 경로를 따라 관심 장소를 열거하거나 요약할 수 있습니다.
서비스는 프로토콜 버퍼 파일에 정의되며, 이 파일은 클라이언트와 서버가 서로 통신할 수 있도록 상용구 코드를 생성하는 데 사용되므로 이 기능을 구현하는 데 드는 시간과 노력을 절약할 수 있습니다.
이 생성된 코드는 서버와 클라이언트 간의 복잡한 통신뿐만 아니라 데이터 직렬화 및 역직렬화도 처리합니다.
학습할 내용
- 프로토콜 버퍼를 사용하여 서비스 API를 정의하는 방법
- 자동 코드 생성을 사용하여 프로토콜 버퍼 정의에서 gRPC 기반 클라이언트와 서버를 빌드하는 방법
- gRPC를 사용한 클라이언트-서버 통신에 대한 이해
이 Codelab은 gRPC를 처음 접하거나 gRPC를 다시 살펴보려는 Python 개발자 또는 분산 시스템 빌드에 관심이 있는 모든 사용자를 대상으로 합니다. 이전 gRPC 경험은 필요하지 않습니다.
2. 시작하기 전에
필요한 항목
- Python 3.9 이상 Python 3.13을 권장합니다. 플랫폼별 설치 안내는 Python 설정 및 사용을 참고하세요. 또는 uv 또는 pyenv와 같은 도구를 사용하여 시스템이 아닌 Python을 설치합니다.
- pip를 사용하여 Python 패키지를 설치합니다.
- venv를 사용하여 Python 가상 환경을 만듭니다.
ensurepip
및 venv
패키지는 Python 표준 라이브러리의 일부이며 일반적으로 기본적으로 사용할 수 있습니다.
하지만 일부 Debian 기반 배포판 (Ubuntu 포함)에서는 python을 재배포할 때 이를 제외합니다. 패키지를 설치하려면 다음을 실행하세요.
sudo apt install python3-pip python3-venv
코드 가져오기
학습을 간소화하기 위해 이 Codelab에서는 시작하는 데 도움이 되는 사전 빌드된 소스 코드 스캐폴드를 제공합니다. 다음 단계에서는 grpc_tools.protoc
프로토콜 버퍼 컴파일러 플러그인을 사용한 gRPC 코드 생성을 비롯하여 애플리케이션을 완료하는 방법을 안내합니다.
grpc-codelabs
이 Codelab의 스캐폴드 소스 코드는 codelabs/grpc-python-getting-started/start_here 디렉터리에서 확인할 수 있습니다. 코드를 직접 구현하지 않으려면 완료된 소스 코드가 completed
디렉터리에 있습니다.
먼저 Codelab 작업 디렉터리를 만들고 해당 디렉터리로 이동합니다.
mkdir grpc-python-getting-started && cd grpc-python-getting-started
Codelab을 다운로드하고 압축을 풉니다.
curl -sL https://github.com/grpc-ecosystem/grpc-codelabs/archive/refs/heads/v1.tar.gz \
| tar xvz --strip-components=4 \
grpc-codelabs-1/codelabs/grpc-python-getting-started/start_here
또는 codelab 디렉터리만 포함된 .zip 파일을 다운로드하고 직접 압축을 해제할 수 있습니다.
3. 서비스 정의
첫 번째 단계는 프로토콜 버퍼 인터페이스 정의 언어를 사용하여 애플리케이션의 gRPC 서비스, RPC 메서드, 요청 및 응답 메시지 유형을 정의하는 것입니다. 서비스에서 제공하는 기능:
- 서버가 구현하고 클라이언트가 호출하는 RPC 메서드
GetFeature
Point
및Feature
메시지 유형은GetFeature
메서드를 사용할 때 클라이언트와 서버 간에 교환되는 데이터 구조입니다. 클라이언트는 서버에 대한GetFeature
요청에서 지도 좌표를Point
로 제공하고 서버는 해당 좌표에 있는 항목을 설명하는 해당Feature
로 응답합니다.
이 RPC 메서드와 메시지 유형은 모두 제공된 소스 코드의 protos/route_guide.proto
파일에 정의됩니다.
프로토콜 버퍼는 일반적으로 protobuf로 알려져 있습니다. gRPC 용어에 대한 자세한 내용은 gRPC의 핵심 개념, 아키텍처, 수명 주기를 참고하세요.
메시지 유형
소스 코드의 protos/route_guide.proto
파일에서 먼저 Point
메시지 유형을 정의합니다. Point
는 지도상의 위도-경도 좌표 쌍을 나타냅니다. 이 Codelab에서는 좌표에 정수를 사용합니다.
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
1
및 2
은 message
구조의 각 필드에 대한 고유 ID 번호입니다.
다음으로 Feature
메시지 유형을 정의합니다. Feature
는 Point
로 지정된 위치에 있는 항목의 이름이나 우편 주소에 string
필드를 사용합니다.
message Feature {
// The name or address of the feature.
string name = 1;
// The point where the feature is located.
Point location = 2;
}
서비스 메서드
route_guide.proto
파일에는 애플리케이션 서비스에서 제공하는 하나 이상의 메서드를 정의하는 RouteGuide
라는 service
구조가 있습니다.
RouteGuide
정의 내에 rpc
메서드 GetFeature
를 추가합니다. 앞서 설명한 것처럼 이 메서드는 지정된 좌표 집합에서 위치의 이름이나 주소를 조회하므로 GetFeature
가 지정된 Point
에 대해 Feature
를 반환하도록 합니다.
service RouteGuide {
// Definition of the service goes here
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
}
이는 단항 RPC 메서드입니다. 클라이언트가 서버에 요청을 보내고 로컬 함수 호출과 마찬가지로 응답이 돌아오기를 기다리는 간단한 RPC입니다.
4. 클라이언트 및 서버 코드 생성
그런 다음 프로토콜 버퍼 컴파일러를 사용하여 .proto
파일에서 클라이언트와 서버 모두의 상용구 gRPC 코드를 생성합니다.
gRPC Python 코드 생성을 위해 grpcio-tools가 생성되었습니다. 다음이 포함됩니다.
message
정의에서 Python 코드를 생성하는 일반 protoc 컴파일러service
정의에서 Python 코드 (클라이언트 및 서버 스텁)를 생성하는 gRPC protobuf 플러그인
pip를 사용하여 grpcio-tools
Python 패키지를 설치합니다. 프로젝트의 종속 항목을 시스템 패키지에서 격리하기 위해 새 Python 가상 환경 (venv)을 만들어 보겠습니다.
python3 -m venv --upgrade-deps .venv
bash/zsh 셸에서 가상 환경을 활성화하려면 다음을 실행합니다.
source .venv/bin/activate
Windows 및 비표준 셸의 경우 https://docs.python.org/3/library/venv.html#how-venvs-work의 표를 참고하세요.
그런 다음 grpcio-tools를 설치합니다. 이렇게 하면 grpcio 패키지도 설치됩니다.
pip install grpcio-tools
다음 명령어를 사용하여 Python 상용구 코드를 생성합니다.
python -m grpc_tools.protoc --proto_path=./protos \
--python_out=. --pyi_out=. --grpc_python_out=. \
./protos/route_guide.proto
그러면 route_guide.proto
에 정의된 인터페이스에 대해 다음 파일이 생성됩니다.
route_guide_pb2.py
에는message
정의에서 생성된 클래스를 동적으로 생성하는 코드가 포함되어 있습니다.route_guide_pb2.pyi
은message
정의에서 생성된 '스텁 파일' 또는 '타입 힌트 파일'입니다. 구현 없이 서명만 포함합니다. 스텁 파일은 IDE에서 더 나은 자동 완성 및 오류 감지를 제공하는 데 사용할 수 있습니다.route_guide_pb2_grpc.py
는service
정의에서 생성되며 gRPC 관련 클래스와 함수를 포함합니다.
gRPC 관련 코드에는 다음이 포함됩니다.
RouteGuideStub
: gRPC 클라이언트가 RouteGuide RPC를 호출하는 데 사용할 수 있습니다.RouteGuide
서비스 구현의 인터페이스를 정의하는RouteGuideServicer
RouteGuideServicer
을 gRPC 서버에 등록하는 데 사용되는add_RouteGuideServicer_to_server
함수
5. 서비스 만들기
먼저 RouteGuide
서버를 만드는 방법을 살펴보겠습니다. RouteGuide
서버를 만들고 실행하는 작업은 다음 두 가지 작업 항목으로 나뉩니다.
- 서비스의 실제 '작업'을 실행하는 함수를 사용하여 서비스 정의에서 생성된 서비스 인터페이스를 구현합니다.
- 특정 포트에서 gRPC 서버를 실행하여 클라이언트의 요청을 수신 대기하고 응답을 전송합니다.
초기 RouteGuide
서버는 start_here/route_guide_server.py
에서 찾을 수 있습니다.
RouteGuide 구현
route_guide_server.py
에는 생성된 클래스 route_guide_pb2_grpc.RouteGuideServicer
를 서브클래스화하는 RouteGuideServicer
클래스가 있습니다.
# RouteGuideServicer provides an implementation
# of the methods of the RouteGuide service.
class RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer):
RouteGuideServicer
은 모든 RouteGuide
서비스 메서드를 구현합니다.
간단한 RPC 구현을 자세히 살펴보겠습니다. GetFeature
메서드는 클라이언트에서 Point
을 가져와 데이터베이스에서 해당하는 기능 정보를 Feature
로 반환합니다.
def GetFeature(self, request, context):
feature = get_feature(self.db, request)
if feature is None:
return route_guide_pb2.Feature(name="", location=request)
else:
return feature
이 메서드에는 RPC에 대한 route_guide_pb2.Point
요청과 제한 시간 한도와 같은 RPC 관련 정보를 제공하는 grpc.ServicerContext
객체가 전달됩니다. route_guide_pb2.Feature
응답을 반환합니다.
서버 시작
모든 RouteGuide
메서드를 구현했다면 다음 단계는 클라이언트가 실제로 서비스를 사용할 수 있도록 gRPC 서버를 시작하는 것입니다.
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
route_guide_pb2_grpc.add_RouteGuideServicer_to_server(
RouteGuideServicer(),
server,
)
listen_addr = "localhost:50051"
server.add_insecure_port(listen_addr)
print(f"Starting server on {listen_addr}")
server.start()
server.wait_for_termination()
서버 start()
메서드는 차단되지 않습니다. 요청을 처리하기 위해 새 스레드가 인스턴스화됩니다. server.start()
를 호출하는 스레드는 그동안 다른 작업을 실행하지 않는 경우가 많습니다. 이 경우 server.wait_for_termination()
를 호출하여 서버가 종료될 때까지 호출 스레드를 깔끔하게 차단할 수 있습니다.
6. 클라이언트 만들기
이 섹션에서는 RouteGuide
서비스의 클라이언트를 만드는 방법을 살펴봅니다. start_here/route_guide_client.py
에서 초기 클라이언트 코드를 확인할 수 있습니다.
스텁 만들기
서비스 메서드를 호출하려면 먼저 스텁을 만들어야 합니다.
route_guide_client.py
파일 내의 .proto
에서 생성된 route_guide_pb2_grpc
모듈의 RouteGuideStub
클래스를 인스턴스화합니다.
channel = grpc.insecure_channel("localhost:50051")
stub = route_guide_pb2_grpc.RouteGuideStub(channel)
서비스 메서드 호출
단일 응답을 반환하는 RPC 메서드(response-unary 메서드라고 함)의 경우 gRPC Python은 동기(차단) 및 비동기(비차단) 제어 흐름 시맨틱을 모두 지원합니다.
간단한 RPC
먼저 서비스를 호출할 Point
를 정의합니다. 이는 route_guide_pb2
패키지에서 일부 속성을 사용하여 객체를 인스턴스화하는 것만큼 간단해야 합니다.
point = route_guide_pb2.Point(latitude=412346009, longitude=-744026814)
간단한 RPC GetFeature
에 대한 동기 호출은 로컬 메서드를 호출하는 것만큼 간단합니다. RPC 호출은 서버가 응답할 때까지 기다리며 응답을 반환하거나 예외를 발생시킵니다. 다음과 같이 메서드를 호출하고 응답을 확인할 수 있습니다.
feature = stub.GetFeature(point)
print(feature)
Feature 객체의 필드를 검사하고 요청 결과를 출력할 수 있습니다.
if feature.name:
print(f"Feature called '{feature.name}' at {format_point(feature.location)}")
else:
print(f"Found no feature at at {format_point(feature.location)}")
7. 사용해 보기
서버를 실행합니다.
python route_guide_server.py
다른 터미널에서 가상 환경을 다시 활성화한 다음 클라이언트를 실행합니다.
python route_guide_client.py
다음과 같은 출력이 표시됩니다. 명확성을 위해 타임스탬프는 생략했습니다.
name: "16 Old Brook Lane, Warwick, NY 10990, USA" location { latitude: 412346009 longitude: -744026814 } Feature called '16 Old Brook Lane, Warwick, NY 10990, USA' at latitude: 412346009, longitude: -744026814
8. 다음 단계
- gRPC 소개 및 핵심 개념에서 gRPC의 작동 방식을 알아보세요.
- 기본사항 튜토리얼 살펴보기
- Python API 참조 살펴보기