본문 바로가기
IT & Tech 정보

🚀 gRPC 서버·클라이언트 구현: Go + Protocol Buffers

by 지식과 지혜의 나무 2025. 5. 25.
반응형


gRPC는 고성능 원격 절차 호출(RPC)을 쉽게 구현할 수 있는 프레임워크입니다.
이번에는 Go와 Protocol Buffers를 사용해 간단한 gRPC 서비스(“HelloService”)를 정의·구현해보겠습니다.



📋 목차
1. gRPC 개요
2. 프로젝트 초기 설정
3. Protobuf 정의 (.proto)
4. 코드 생성 (protoc)
5. 서버 구현 (Go)
6. 클라이언트 구현 (Go)
7. 실행 및 테스트
8. 실전 팁



1️⃣ gRPC 개요
• Protocol Buffers: 구글이 만든 직렬화(serialization) 포맷, 메시지 스키마를 .proto 파일로 정의
• gRPC: HTTP/2 기반으로 양방향 스트리밍·플로우 제어·다양한 언어 바인딩 지원
• Use Case: 마이크로서비스 간 통신, 모바일↔백엔드 통신, 대용량 데이터 스트리밍



2️⃣ 프로젝트 초기 설정

# 1) 작업 디렉터리 생성
mkdir go-grpc-demo && cd go-grpc-demo

# 2) Go 모듈 초기화
go mod init github.com/yourusername/go-grpc-demo

# 3) 의존성 설치
go get google.golang.org/grpc
go get google.golang.org/protobuf/cmd/protoc-gen-go
go get google.golang.org/grpc/cmd/protoc-gen-go-grpc

# 4) protoc 설치 (Mac/Linux)
# Mac (Homebrew)
brew install protobuf
# Linux (apt)
sudo apt install -y protobuf-compiler




3️⃣ Protobuf 정의 (hello.proto)

syntax = "proto3";

package hellopb;

option go_package = "github.com/yourusername/go-grpc-demo/hellopb";

// 서비스 정의
service HelloService {
  // Unary RPC
  rpc SayHello(HelloRequest) returns (HelloReply);
}

// 메시지 타입
message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

• package: 네임스페이스
• option go_package: Go 코드 생성 시 경로 지정



4️⃣ 코드 생성 (protoc)

# 1) hellopb 디렉터리 생성
mkdir -p hellopb

# 2) 프로토콜 컴파일
protoc --go_out=. --go-grpc_out=. hello.proto

• --go_out=.: 메시지 타입 .pb.go 생성
• --go-grpc_out=.: 서비스 인터페이스 .pb.grpc.go 생성



5️⃣ 서버 구현 (Go)

// server.go
package main

import (
  "context"
  "log"
  "net"

  "github.com/yourusername/go-grpc-demo/hellopb"
  "google.golang.org/grpc"
)

type server struct {
  hellopb.UnimplementedHelloServiceServer
}

func (s *server) SayHello(ctx context.Context, req *hellopb.HelloRequest) (*hellopb.HelloReply, error) {
  name := req.GetName()
  return &hellopb.HelloReply{
    Message: "Hello, " + name + "!",
  }, nil
}

func main() {
  lis, err := net.Listen("tcp", ":50051")
  if err != nil {
    log.Fatalf("failed to listen: %v", err)
  }

  grpcServer := grpc.NewServer()
  hellopb.RegisterHelloServiceServer(grpcServer, &server{})

  log.Println("gRPC 서버 시작: :50051")
  if err := grpcServer.Serve(lis); err != nil {
    log.Fatalf("failed to serve: %v", err)
  }
}

• UnimplementedHelloServiceServer를 임베드해 인터페이스 구현
• RegisterHelloServiceServer로 서비스 등록



6️⃣ 클라이언트 구현 (Go)

// client.go
package main

import (
  "context"
  "log"
  "time"

  "github.com/yourusername/go-grpc-demo/hellopb"
  "google.golang.org/grpc"
)

func main() {
  conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
  if err != nil {
    log.Fatalf("failed to connect: %v", err)
  }
  defer conn.Close()

  client := hellopb.NewHelloServiceClient(conn)

  ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  defer cancel()

  resp, err := client.SayHello(ctx, &hellopb.HelloRequest{Name: "gRPC"})
  if err != nil {
    log.Fatalf("error calling SayHello: %v", err)
  }
  log.Printf("Response: %s", resp.GetMessage())
}

• grpc.Dial로 서버 연결 (WithInsecure는 인증 없이 통신할 때)
• NewHelloServiceClient로 클라이언트 객체 생성



7️⃣ 실행 및 테스트

# 1) 서버 실행 (터미널 1)
go run server.go

# 2) 클라이언트 실행 (터미널 2)
go run client.go
# → 로그: "Response: Hello, gRPC!"

• 서버가 포트 50051에서 대기
• 클라이언트가 요청 후 응답 메시지 출력



8️⃣ 실전 팁
• TLS 적용: grpc.Creds + 인증서 파일로 보안 강화
• 양방향 스트리밍: rpc StreamChat(stream ChatMessage) returns (stream ChatMessage); 식으로 정의
• 메타데이터: 인증 토큰·트레이싱 ID를 metadata.NewOutgoingContext로 전송
• 에러 처리: status.Errorf(codes.Unauthenticated, "authentication required")
• 로드 밸런싱: Kubernetes 서비스+Headless Service 또는 Envoy/LB 연동



이제 Go와 Protocol Buffers로 gRPC 서버·클라이언트를 기본 형태로 완성했습니다.
다음 주제에서는 Terraform으로 AWS 인프라 코드 관리를 다뤄보겠습니다!

반응형