gRPC 소개
gRPC는 Google에서 개발한 고성능, 범용 RPC(Remote Procedure Call) 프레임워크입니다. 이를 통해 서로 다른 시스템 간의 통신을 쉽게 구현할 수 있습니다. gRPC는 HTTP/2를 기반으로 하며, 프로토콜 버퍼(Protocol Buffers)를 사용하여 효율적인 직렬화 및 역직렬화를 제공합니다.
gRPC 설치
gRPC와 Protocol Buffers를 설치하려면 다음 명령어를 사용합니다.
sudo apt-get install -y build-essential autoconf libtool pkg-config
git clone -b v1.39.1 https://github.com/grpc/grpc
cd grpc
git submodule update --init
make
sudo make install
cd third_party/protobuf
sudo make install
gRPC 프로젝트 생성
gRPC를 사용하여 간단한 분산 시스템을 구축합니다. 여기서는 간단한 계산기 서버와 클라이언트를 구현합니다.
1. Protocol Buffers 파일 정의
프로젝트 루트에 calculator.proto
파일을 생성하고 다음 내용을 추가합니다.
syntax = "proto3";
package calculator;
service Calculator {
rpc Add (AddRequest) returns (AddResponse);
rpc Subtract (SubtractRequest) returns (SubtractResponse);
}
message AddRequest {
int32 a = 1;
int32 b = 2;
}
message AddResponse {
int32 result = 1;
}
message SubtractRequest {
int32 a = 1;
int32 b = 2;
}
message SubtractResponse {
int32 result = 1;
}
2. Protocol Buffers 파일 컴파일
다음 명령어를 사용하여 Protocol Buffers 파일을 컴파일합니다.
protoc -I=. --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` calculator.proto
protoc -I=. --cpp_out=. calculator.proto
이 명령어는 calculator.grpc.pb.h
와 calculator.pb.h
헤더 파일을 생성합니다.
gRPC 서버 구현
gRPC 서버를 구현합니다.
1. CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(gRPCExample)
set(CMAKE_CXX_STANDARD 17)
find_package(gRPC CONFIG REQUIRED)
find_package(Protobuf CONFIG REQUIRED)
add_executable(calculator_server
calculator_server.cpp
calculator.grpc.pb.cc
calculator.pb.cc
)
target_link_libraries(calculator_server
gRPC::grpc++_unsecure
protobuf::libprotobuf
)
2. calculator_server.cpp
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#include "calculator.grpc.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using calculator::Calculator;
using calculator::AddRequest;
using calculator::AddResponse;
using calculator::SubtractRequest;
using calculator::SubtractResponse;
class CalculatorServiceImpl final : public Calculator::Service {
Status Add(ServerContext* context, const AddRequest* request, AddResponse* response) override {
int32_t result = request->a() + request->b();
response->set_result(result);
return Status::OK;
}
Status Subtract(ServerContext* context, const SubtractRequest* request, SubtractResponse* response) override {
int32_t result = request->a() - request->b();
response->set_result(result);
return Status::OK;
}
};
void RunServer() {
std::string server_address("0.0.0.0:50051");
CalculatorServiceImpl service;
ServerBuilder builder;
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
server->Wait();
}
int main(int argc, char** argv) {
RunServer();
return 0;
}
gRPC 클라이언트 구현
gRPC 클라이언트를 구현합니다.
1. CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(gRPCExample)
set(CMAKE_CXX_STANDARD 17)
find_package(gRPC CONFIG REQUIRED)
find_package(Protobuf CONFIG REQUIRED)
add_executable(calculator_client
calculator_client.cpp
calculator.grpc.pb.cc
calculator.pb.cc
)
target_link_libraries(calculator_client
gRPC::grpc++_unsecure
protobuf::libprotobuf
)
2. calculator_client.cpp
#include <iostream>
#include <memory>
#include <grpcpp/grpcpp.h>
#include "calculator.grpc.pb.h"
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using calculator::Calculator;
using calculator::AddRequest;
using calculator::AddResponse;
using calculator::SubtractRequest;
using calculator::SubtractResponse;
class CalculatorClient {
public:
CalculatorClient(std::shared_ptr<Channel> channel) : stub_(Calculator::NewStub(channel)) {}
int32_t Add(int32_t a, int32_t b) {
AddRequest request;
request.set_a(a);
request.set_b(b);
AddResponse response;
ClientContext context;
Status status = stub_->Add(&context, request, &response);
if (status.ok()) {
return response.result();
} else {
std::cerr << "RPC failed" << std::endl;
return -1;
}
}
int32_t Subtract(int32_t a, int32_t b) {
SubtractRequest request;
request.set_a(a);
request.set_b(b);
SubtractResponse response;
ClientContext context;
Status status = stub_->Subtract(&context, request, &response);
if (status.ok()) {
return response.result();
} else {
std::cerr << "RPC failed" << std::endl;
return -1;
}
}
private:
std::unique_ptr<Calculator::Stub> stub_;
};
int main(int argc, char** argv) {
CalculatorClient client(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()));
int32_t a = 10;
int32_t b = 20;
int32_t sum = client.Add(a, b);
std::cout << "Sum: " << sum << std::endl;
int32_t difference = client.Subtract(a, b);
std::cout << "Difference: " << difference << std::endl;
return 0;
}
빌드 및 실행
1. 서버 빌드 및 실행
mkdir build
cd build
cmake ..
make
./calculator_server
2. 클라이언트 빌드 및 실행
mkdir build
cd build
cmake ..
make
./calculator_client
이제 클라이언트에서 서버로 RPC 호출을 보내고, 서버에서 요청을 처리하여 결과를 반환합니다.
이제 24일차의 학습을 마쳤습니다. gRPC를 사용하여 간단한 분산 시스템을 구축하고 서버와 클라이언트를 구현해보았습니다.
질문이나 피드백이 있으면 언제든지 댓글로 남겨 주세요. 내일은 "CMake를 이용한 빌드 시스템 관리"에 대해 학습하겠습니다.
'-----ETC----- > C++ 고급 프로그래밍과 응용 프로젝트 시리즈' 카테고리의 다른 글
[C++ 고급 프로그래밍과 응용 프로젝트 시리즈] Day 26: C++로 네트워크 프로그래밍 (소켓 프로그래밍) (0) | 2024.08.01 |
---|---|
[C++ 고급 프로그래밍과 응용 프로젝트 시리즈] Day 27: C++에서의 데이터베이스 연동 (SQLite, MySQL) (0) | 2024.08.01 |
[C++ 고급 프로그래밍과 응용 프로젝트 시리즈] Day 25: CMake를 이용한 빌드 시스템 관리 (0) | 2024.08.01 |
[C++ 고급 프로그래밍과 응용 프로젝트 시리즈] Day 22: Boost 라이브러리 소개 및 활용 (0) | 2024.08.01 |
[C++ 고급 프로그래밍과 응용 프로젝트 시리즈] Day 23: Qt를 이용한 GUI 프로그래밍 (0) | 2024.08.01 |